Home > Back-end >  why cant I compare a pointer pointing to one character to a single character?
why cant I compare a pointer pointing to one character to a single character?

Time:09-28

for my assignment were making a bank database application and for the menu the user must be allowed to type "partial or full" option name. For example for 'add' they can type, add, ad, or a nothing else to call the add function. My problem is that when the user types just a i get a segfault error but when I type add or ad it works just fine. Heres my code AND IM SORRY I know the names and values and such are all over the place, the rest of the program is sitting in my text editor. I suspect that the problem resides around the: if (*firstCharA == 'a' || *firstCharA == 'A') area. Please save me

#include <stdio.h>
#include <string.h>
#include "record.h"
#include "database.h"


int debug = 0;

void getaddress(int, char [], char []);

int main ()
{
    struct record * start = NULL;
    int on = 0;
    const char userInput[60];

    int addRec;
    const char add[7] = "add";

    int printAllRec;
    char printall[] = "printall";

    int findRec;
    char find[] = "find";

    int deleteRec;
    char delete[] = "delete";

    int quitPro;
    char quit[] = "quit";



    printf("\nWelcome to the ZaeBank database! Here you can get all of your bank record needs from adding a record to finding a record!\n");

    printf("To get started, type either add, printall or find and then hit enter!\n");

    while (on < 1)
    {

        printf("\nadd: add a bank record and store it in the ZaeBank database\n");
        printf("\nprintall: print all of the currcently existing bank records in the ZaeBank database\n");
        printf("\nfind: find a currently existing bank record in the ZaeBank database\n");
        printf("\ndelete: delete a currently existing bank record in the ZaeBank database\n");
        printf("\nquit: type 'quit' to quit the program\n");

        scanf("%s", &userInput);

        char *firstCharA;
        char *firstCharP;
        char *firstCharF;
        char *firstCharD;
        char *firstCharQ;

        firstCharA = strpbrk(userInput, add);
        firstCharP = strpbrk(userInput, printall);
        firstCharF = strpbrk(userInput, find);
        firstCharD = strpbrk(userInput, delete);
        firstCharQ = strpbrk(userInput, quit);

        addRec = strcmp(userInput, add);
        printAllRec = strcmp(userInput, printall);
        findRec = strcmp(userInput, find);
        deleteRec = strcmp(userInput, delete);
        quitPro = strcmp(userInput, quit);


        if (*firstCharA == 'a' || *firstCharA == 'A')
        {
            if (addRec == 0)
            {
                printf("1");
            }
            else if (addRec < 0)
            {
                printf("2");
            }

        }

CodePudding user response:

  • strpbrk will look for the first character out of any of the characters provided. It does not search for a sub string, it doesn't care about what order the characters passed to it are, in relation to each other. Also, it is case-sensitive, so it does not make sense to first call strpbrk with a lower case string, then checking the result for upper case.

  • It might be more sensible to first convert the user input to lower case, by for example calling tolower on each character in a loop. Then afterwards search for matching sub strings rather than matching characters. You can search for sub strings using strstr.

  • No matter which search function you use, you should check the result to see if the function found anything at all. Functions like strpbrk and strstr return NULL in case they fail to find anything.

  • Your while loop is always true and goes on forever.

CodePudding user response:

How I would approach this problem: ctype.h includes useful classifying and converting functions that will probably help. isspace also includes line-returns and tabs, which is useful when working with user input.

#include <ctype.h> /* tolower isspace */

To separate input and logic, it is useful to have some kind of numeric value that represents state. This is commonly an enum.

enum action { NONE, ADD, PRINTALL, FIND, DELETE, QUIT };
static const char *action[] =
    { "none", "add", "printall", "find", "delete", "quit" };

This allows easy testing the solution. That is, test if the user input, appropriately transformed, is a prefix of any of the actions.

#include <assert.h>
...
    enum action act;
    act = parse_action(""), assert(act == NONE);
    act = parse_action("A"), assert(act == ADD);
    act = parse_action(" aD \n"), assert(act == ADD);
    act = parse_action("as"), assert(act == NONE);
    act = parse_action("f"), assert(act == FIND);
    act = parse_action("find"), assert(act == FIND);
    act = parse_action("foo"), assert(act == NONE);
    act = parse_action(" FiN \t\r\n"), assert(act == FIND);
...

Make sure to test the empty string. In general, the data structure that is suited to this is a prefix tree. One can easily fake it by checking each of the five entries individually; the lowest common sub-sequence between each pair of values, in this case, is the empty string. One will have to treat this specially if one doesn't want it to return the first thing it's compared against, (which could be desired, but this would be good to explain.)

  •  Tags:  
  • c
  • Related