Andy
Andy

Reputation: 10840

What does the ? mean when outputting a string using printf and is strcmp supposed to return a zero for matches (in C)?

Point of HW is it should read this from a file:

int func(int arg) { int x = 7; char c = 'a'; arg = x + c; return arg; }

and output this:

func, arg, x, c
//or optionally also the next line
int, char, return

So my issue is on getting question marks on my output for characters that should be appearing, and strcmp is not returning a zero for my if statement which requires it to work (note: I have a lot of comments and printf's to help me figure out where I am going wrong):

while((d=fgetc(function_file)) != EOF) {
    //start by checking for any defines and just looping until a new line character comes up
    if( d == '#')
        flag = true;

    if((d == '\n') && (flag)){
        //flag which says if I am searching for a newline but only after a define/include 
        //was found will I say the flag is not needed anymore to allow normal parsing
        flag = false;
    } //end of check for a define function

    if( (flag == false) && (d != '#') ) {

        //this is where the main chunk of code goes to do all the parsing
        if((d != ' ') && (d != '\t') && (d !='\n') && (d != '{') && (d != '}') && (d != '(') && (d != ')') && (d != '*') && (d != '=') && (d != '+')) {

            printf("Character read is : %c\n", d);
            start = true;
            temp[count] = c;
            count++;
        }


    }//end of main chunk of code
        if((start == true) && ((d == ' ') || (d == '(') || (d == ')') || (d == '{') || (d == '}'))) {
            //end a string and compare it hear
            if(match == false) {
            temp[count] = '\0';
        printf("String: %s\n", temp);//*********************************DEBUGGING***********

            start = false;
            int compare;
            for(compare = 0; compare < key_counter; compare++) {
                int optimus;
                optimus = strcmp(keywords[compare], temp); //************** ONE OF THE ERRORS IS HERE***************************************?
                if(optimus == 0){
                    //printf("this is actually runnning");//*********************************DEBUGGING***********
                    int len = strlen(temp);
                    bizarro_keywords[bizarro_key_counter] = (char *)malloc(sizeof(char) * (len +1));
                    memcpy(bizarro_keywords[bizarro_key_counter], temp, len +1);
                    printf("\nWhats inside bizarro_key_counter right after it is allocated memory: %s", bizarro_keywords[bizarro_key_counter]);
                    bizarro_key_counter++;
                    match = true;
                }

            }

            int x;
            for(x = 0; x < count; x++)
                temp[x] = '\0';
            count = 0;


        } else { //if match equals true just grab the next available string 
            //printf("is this one ever running?");
            temp[count] = '\0';
            start = false;
            printf("String: %s\n", temp);

                    int len = strlen(temp);
                    identifiers[iden_counter] = (char *)malloc(sizeof(char) * (len +1));
                    memcpy(identifiers[iden_counter], temp, len +1);
                    iden_counter++;
                    match = false;



                    int x;
                    for(x = 0; x < count; x++)
                        temp[x] = '\0';
                    count = 0;

            }   
        }

}//end of while loop for reading the whole file

This is my output:

Character read is : i
Character read is : n
Character read is : t
String: ???
Character read is : f
Character read is : u
Character read is : n
Character read is : c
String: ????
Character read is : i
Character read is : n
Character read is : t
String: ???
Character read is : a
Character read is : r
Character read is : g
String: ???
Character read is : i
Character read is : n
Character read is : t
String: ???
Character read is : x
String: ?
Character read is : 7
Character read is : ;
String: ??
Character read is : c
Character read is : h
Character read is : a
Character read is : r
String: ????
Character read is : c
String: ?
Character read is : '
Character read is : a
Character read is : '
Character read is : ;
String: ????
Character read is : a
Character read is : r
Character read is : g
String: ???
Character read is : x
String: ?
Character read is : c
Character read is : ;
String: ??
Character read is : r
Character read is : e
Character read is : t
Character read is : u
Character read is : r
Character read is : n
String: ??????
Character read is : a
Character read is : r
Character read is : g
Character read is : ;
String: ????

I am new to C, and I am lost as to why I am getting that output. Hints please.

Upvotes: 0

Views: 727

Answers (2)

LihO
LihO

Reputation: 42103

From what I understand you just want to read line from the input file and split it into tokens. You could use strtok function instead of reading characters from the file:

char* keywords[] = { "int", "char", "return" };
int i = 0, j, keywordsCount = 3;
FILE* f = fopen("a.txt", "r");
char line[1000], *token;
while (fgets(line, 1000, f) != NULL) // read line
{
    char* token = strtok(line, " \t\n{}()*+=,;");
    while (token != NULL)
    {
        printf("String %d:%s", i++, token);

        for (j = 0; j < keywordsCount; ++j)
            if (strcmp(token, keywords[j]) == 0)
            {
                printf(" <-- Look, it's keyword!");
                break; // breaks for, not while
            }

        putchar('\n');
        token = strtok(NULL, " \t\n{}()*+=,;");
    }
}

Note that I use '\n' character in delimiters string because fgets function reads line into buffer that will include '\n' at the end.

Content of file a.txt:

int func(int arg) { int x = 7; char c = 'a'; arg = x + c; return arg; }

Output:

String 0:int <-- Look, it's keyword!
String 1:func
String 2:int <-- Look, it's keyword!
String 3:arg
String 4:int <-- Look, it's keyword!
String 5:x
String 6:7
String 7:char <-- Look, it's keyword!
String 8:c
String 9:'a'
String 10:arg
String 11:x
String 12:c
String 13:return <-- Look, it's keyword!
String 14:arg

Upvotes: 1

AndersK
AndersK

Reputation: 36102

Your code is a bit difficult to read - at least part four (despite the comments) because it is just too long.

You should split up your function into several smaller ones, you even already have the structure in place step 1-4. Now since you are reusing variables declared before there may sneak in issues like count not being == 0 when you get to step four. since there are so many twist and turns its a bit difficult to see the problem

when you such lexical analysis it is often better to use a state machine, switch statements are good for this e.g.

typedef enum { Idle, Include , ... } states_t;
states_t state=Idle;

switch (state)
{
   case Idle:
      switch ( d )
      { 
         case '#':
           state = Include;
           break;
     ...
     break;
   case Include:
     ...
     break;

      break;

if you don't have a debugger include assert.h and put asserts in your code to make sure all assumptions are caught i.e. assert( count == 0 ); before step four may be a good thing.

use strcpy or better strncpy instead of memcpy when copying, the strcpy-family stops to copying when it encounters a \0 which is a bit more effective (it copies the \0 as well).

Upvotes: 0

Related Questions