0

I'm struggling to compare the contents of a struct to a variable. There are 10 structs in array1 with the variables value and count. I need to go through every value variable until I find the one matching tempVal and then increment the corresponding count, then the search can end. If it's not found the function will return -1.

I have the following code that runs fine but doesn't work, I have a feeling it may be something wrong with the strcmp line but I'm not sure. Cheers for any input.

int valCheck(char *tempVal){ int j; for(j=0;j<10;j++){ if(strcmp(array1[j].value, tempVal) == 0){ array1[j].count++; //increment its count break; } } } 

Edited full:

#include <stdio.h> #include <stdlib.h> #include <errno.h> struct values { char value[64]; int count; }; struct values array1[100]; //check if value exists in array int valCheck(char *tempVal) { int j; for(j=0;j<10;j++) { if(strcmp(array1[j].value, tempVal) == 0) { array1[j].count++; //increment its count //return j; // <== return index of found element } } return -1; } int main() { FILE * input; int i; char tempVal[] ="hello"; input = fopen("random.txt","r"); for (i=0;i<=10;i++) //go through the 10 elements in text file { //scan each word into a temporary variable // **** NOT COMPLETE, JUST USING TEMPWORD ASSIGNED FOR NOW int checkedVal = valCheck(&tempVal); //if wordCheck returns -1 add the word to the array //otherwise do nothing as a duplicate has appeared if(checkedVal == -1){ fscanf(input, "%s",array1[i].value); } printf("WORD %i: %s ",i,array1[i].value); printf(" COUNT IS: %i", array1[i].count); printf("\n"); } fclose(input); return 0; } 
8
  • 1
    please define doesn't work. Also add the definition of your array1[] structure to the question. Commented Mar 31, 2013 at 12:15
  • 1
    From your code, no one can tell whats wrong. What is array1 ? What is tempVal Commented Mar 31, 2013 at 12:16
  • 2
    Adding a fprintf(stderr, "%d {%s,%s}\n", j, array1[j].value, tempVal); inside the loop will probably enlighten you. Commented Mar 31, 2013 at 12:19
  • 1
    Function strcmp works for C strings, not for structs. It stops when it finds the "null terminator", which could be an arbitrary zero embedded in your struct. Commented Mar 31, 2013 at 12:20
  • 1
    @dasblinkenlight I'm going to assume it would not compile if passed a structure pointer as either parameter to strcmp() I see no casts, and I do see a structure member denote (the value in array1[j].value). Knowing whether this compiles vs. fails-at-runtime would probably narrow quite a bit down. Commented Mar 31, 2013 at 12:24

1 Answer 1

2

Assuming the following:

  • Your array is properly allocated (either on the stack or dynamically) to be at-least-10-elements wide.
  • Your structure member value is a valid char * or fixed-length char[n] buffer.
  • The string data references by the value member of your structure is properly null-terminated.
  • The string data referenced by tempVal is valid and properly null-terminated.
  • You're aware that strcmp() compares case-sensitively
  • You're comment about 100 elements in the array and this code only checking the first ten (10) elements is intentional

My crystal ball tells me that ultimately you need to have your function actually return something.

int valCheck(char *tempVal) { int j; for(j=0;j<10;j++) { if(strcmp(array1[j].value, tempVal) == 0) { array1[j].count++; //increment its count return j; // <== return index of found element } } return -1; // <== return -1 per your description of failure. } 

Note: Your compiler, equipped with decent warning-checks, would easily spot this lack-of-return code. Heed those warnings. Likewise, double-check everything in the bullet list at the top of this answer to make sure what you're going into this with is proper.


EDIT Updated to reflect sample dictionary build for OP.

The following is how I think this is likely to be called. Hope it helps you. I changed a few things:

  • Made the dictionary a little bigger (256)
  • Processes the command line to get the filename. Makes it easier for me to test.
  • Only reports a summary at the end rather than per-word while processing.

I hope it helps.

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> struct values { char value[64]; int count; }; // global array. struct values array1[256]; int n_words = 0; //check if value exists in array int valCheck(const char *tempVal) { int j; for(j=0;j<10;j++) { if(strcmp(array1[j].value, tempVal) == 0) { array1[j].count++; //increment its count return j; } } return -1; } int main(int argc, char *argv[]) { FILE * input = NULL; char tempVal[64]; int i=0; if (argc < 2) { printf("Must specify a filename.\n"); return EXIT_FAILURE; } // open file input = fopen(argv[1],"r"); if (!input) { perror("Failed to open file."); return EXIT_FAILURE; } // read all strings from the file one at a time. while (fscanf(input, "%64s", tempVal) == 1) { int i = valCheck(tempVal); if (i == -1) { if (n_words < sizeof(array1)/sizeof(array1[0])) { strcpy(array1[n_words].value, tempVal); array1[n_words].count = 1; i = n_words++; } else { // error. no more space in dictionary printf("No more space to add word: %s\n", tempVal); } } } fclose(input); // summary report for (i=0;i<n_words;++i) printf("WORD %i: %s, COUNT IS: %i\n", i, array1[i].value, array1[i].count); return EXIT_SUCCESS; } 

Input

hello my name is dave hello I am dave hi 

Output

WORD 0: hello, COUNT IS: 2 WORD 1: my, COUNT IS: 1 WORD 2: name, COUNT IS: 1 WORD 3: is, COUNT IS: 1 WORD 4: dave, COUNT IS: 2 WORD 5: I, COUNT IS: 1 WORD 6: am, COUNT IS: 1 WORD 7: hi, COUNT IS: 1 

Homework

After all of that, I leave you to determine why the following code also works, but uses no temporary buffer to do so (sort of, anyway).

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> struct values { char value[64]; int count; }; // global array. #define MAX_WORDS 256 struct values array1[MAX_WORDS] = {{{0},0}}; int n_words = 0; //check if value exists in array int valCheck(const char *tempVal) { int j; for(j=0; j< n_words; j++) { if(strcmp(array1[j].value, tempVal) == 0) { array1[j].count++; //increment its count return j; } } return -1; } int main(int argc, char *argv[]) { FILE * input = NULL; int i=0; if (argc < 2) { printf("Must specify a filename.\n"); return EXIT_FAILURE; } // open file input = fopen(argv[1],"r"); if (!input) { perror("Failed to open file."); return EXIT_FAILURE; } // read all strings from the file one at a time. while (n_words < MAX_WORDS && fscanf(input, "%64s", array1[n_words].value) == 1) { if (valCheck(array1[n_words].value) == -1) { array1[n_words].count = 1; ++n_words; } } fclose(input); // summary report for (i=0;i<n_words;++i) printf("WORD %i: %s, COUNT IS: %i\n", i, array1[i].value, array1[i].count); return 0; } 

The output is the same as before.

Sign up to request clarification or add additional context in comments.

9 Comments

hmm it doesn't appear that my comparison code was too wrong then, so I must be making a problem elsewhere. I'm pretty sure all those assumptions are met apart from: -The string data references by the value member of your structure is properly null-terminated. -The string data referenced by tempVal is valid and properly null-terminated. I've edited the OP if that helps
@user2209254 Your updated post will always return -1. That return j is there for a reason: to denote success (i.e. a non-(-1) return value. You could just as easily return 0. Anything will do, so long as it is NOT (-1) if you found a match.
ah sorry forgot about that! I did try returning 0 but then it only does the loop once and stops. the file just contains random words delimited by spaces. "hello my name is dave hello I am dave hi" - pretty random !
@user2209254 ok. So the premise is you're reading these strings in, looking them up in you up-to-one-hundred-word dictionary,and if they're already there, bump a reference count, otherwise add it. If that sounds correct you're closer than you may think. Scan the next word into a local var, then use valCheck() to determine if it is present. If it isn't (-1 returned), then add it. you need to keep track of how many words are in your dictionary to use as the top-end of how many comparisons to do, and increment that as you add words. But the only bug in your checker, no ret-val, is fixed.
I did try assigning tempVal the next word in file rather than having a static value using "fscanf(input, "%s",tempVal);" and then in the "if(checkedVal == -1){" block assigning the word using "array1[i].value = tempVal;" but got no success either
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.