3

I have a struct named excuses that has chars, I need to store at least 20 excuses. Then, I need to divide each word of each excuse in an array.

¿How i can do that?

#define excuseLength 256

typedef struct{
    char sentence[excuseLength];
}excuse;

excuse listExcuses[20];

for (int listExcuses_i = 0; listExcuses_i < 20; listExcuses_i++)
{
    char *input;
    scanf("%s", input);
    strcpy(listExcuses[listExcuses_i].sentence, input);

    char* token = strtok(input, " ");
    while(token != NULL){
        printf("token: %s\n", token);
        token = strtok(NULL, " ");
    }
}
  • 2
    In `ListExcuses[arrayExcuses_i] = sentence;`, you cannot assign value to a char array `ListExcuses[arrayExcuses_i] `, instead, you may want to use `strcpy`. And what do you want to do with the split excuse in each sentence? Store it what array? For `strtok`, see [How does strtok() split the string into tokens in C?](http://stackoverflow.com/questions/3889992/how-does-strtok-split-the-string-into-tokens-in-c.) – Neo X Feb 13 '17 at 01:53
  • with the split excuse i want to be able to compare the words with other given words. – Santiago C. Feb 13 '17 at 01:55
  • 1
    `char *input; scanf("%s", input);` : `input` must allocate memory chunk. E.g `char input[256];` , `strtok(input, " ");` : `input` contains no whitespace. Because it is input with `scanf("%s", input);`. (`%s` of `scanf` inputs other than blanks.) – BLUEPIXY Feb 13 '17 at 02:09
  • 1
    Use `fgets` to read input, not `scanf()`. – RoadRunner Feb 13 '17 at 02:13
  • 1
    Also, where is this array that stores these tokens? So far you are just parsing `input` with `strtok()`, and printing the words out. – RoadRunner Feb 13 '17 at 02:23
  • now that I can divide the excuse i'll to that part. thanks! @RoadRunner – Santiago C. Feb 13 '17 at 02:58
  • and thank you @BLUEPIXY that also worked – Santiago C. Feb 13 '17 at 03:00

2 Answers2

2

Here are some things you can add to your solution:

  • Check fgets() for return value, as it returns NULL on error.
  • If you decide to still use scanf(), make sure to use scanf("%255s", input) instead for char input[256]. Using the format specifier %255s instead of the simpe %s checks for excessive input. Overall, it just better to read input using fgets().
  • Remove '\n' character appended by fgets(). This is also good for checking that you don't enter more characters than the limit of 256 in input, and that your sentences don't have a trailing newline after each of them. If you don't remove this newline, then your strtok() delimiter would have to be " \n" instead.
  • #define constants in your code, and use const char* for string literals, such as the delimiter for strtok().
  • You can also add some code to check for empty inputs from fgets(). You could simply use a separate counter, and only increment this counter for valid strings found.
  • It's also strange to have struct with one member, usually structs contain more than one member. You could simply bypass using a struct and use a 2D char array declared as char listexcuses[NUMEXCUSES][EXCUSELENGTH]. This array can hold up to 20 strings, each of which has a maximum length of 256.

Here is some modified code of your approach:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define EXCUSELENGTH 256
#define NUMEXCUSES 20

typedef struct {
    char sentence[EXCUSELENGTH];
} excuse;

int main(void) {
    excuse listexcuses[NUMEXCUSES];
    char input[EXCUSELENGTH] = {'\0'};
    char *word = NULL;
    const char *delim = " ";
    size_t slen, count = 0;

    for (size_t i = 0; i < NUMEXCUSES; i++) {

        printf("\nEnter excuse number %zu:\n", count+1);
        if (fgets(input, EXCUSELENGTH, stdin) == NULL) {
            fprintf(stderr, "Error from fgets(), cannot read line\n");
            exit(EXIT_FAILURE);
        }

        slen = strlen(input);
        if (slen > 0 && input[slen-1] == '\n') {
            input[slen-1] = '\0';
        } else {
            fprintf(stderr, "Too many characters entered in excuse %zu\n", count+1);
            exit(EXIT_FAILURE);
        }

        if (*input) {
            strcpy(listexcuses[count].sentence, input);
            count++;

            printf("\nTokens found:\n");
            word = strtok(input, delim);
            while (word != NULL) {
                printf("%s\n", word);
                word = strtok(NULL, delim);
            }  
        }
    }

    return 0;
} 

As you need to eventually store these tokens somewhere, you will need another form of storing this data. Since you don't know how many tokens you can get, or how long each token is, you may need to use something like char **tokens. This is not an array, but it is a pointer to a pointer. Using this would allow any number of words and any lengths of each word to be stored. You will need dynamic memory allocation for this. The answer in this post will help.

RoadRunner
  • 25,803
  • 6
  • 42
  • 75
1

I changed the scanf for fgets and initialize the char input[256] and with that now it works!

#define excuseLength 256
#define numberExcuses 20

typedef struct{
    char sentence[excuseLength];
}excuse;

excuse listExcuses[20];

for (int listExcuses_i = 0; listExcuses_i < numberExcuses; listExcuses_i++)
{
    char input[256];
    scanf("%s", input);
    fgets(input, 256, stdin);
    strcpy(listExcuses[listExcuses_i].sentence, input);

    char* token = strtok(input, " ");
    while(token != NULL){
        printf("token: %s\n", token);
        token = strtok(NULL, " ");
    }
}