0

I have words separated by \n in a file:

Moscow
Berlin
Lisbon
Amsterdam
Paris
Nairobi

I want to read these words into 2d string array. But when I want to suppress any term of the series, I can't get results.

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

#define K 10

int
main()
{
    int i,j;
    char c;
    int count=0;
    FILE *fp;

    fp = fopen("input1.txt","r");
    if (fp == NULL)
        printf("file not found\n");

    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n')
            count++;
    }

    char chz[count][K];
    while (!feof(fp)) {
        for (i=0;  i<count;  i++) {
            for (j=0;  j<K;  j++) {
                fscanf(fp,"%c",&chz[i][j]);
                if (chz[i][j]=='\n') {
                    break;
                }
            }
            chz[i][j]='\0';
        }
    }
    printf("%c",chz[0][1]);

    return 0;
}

There may also be more city names in the file.So I calculated the number of words in the file in the first place.How can I fix this problem?Thanks...

Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • 1
    After the first `while(fgetc())` loop, the file is at the end. `feof` will (most likely) return true, and the second loop iterates zero times. The only way that loop is entered is if there was a read error, in which case it is an infinite loop. – William Pursell Nov 27 '20 at 22:13
  • https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – William Pursell Nov 27 '20 at 22:15
  • @WilliamPursell Thank you very much for your response.I solved the problem by adding Fseek.But there's one more thing I'm stuck with.Why, for example, when we type chz[3][20], it prints a character.doesn't adding '\0' to the end of the array solve the problem? – martinedenburg Nov 27 '20 at 22:34
  • You need to do `rewind(fp)` after the `fgetc` loop. Otherwise you are already at EOF for the next loop – Craig Estey Nov 27 '20 at 22:35

1 Answers1

0

You need to do rewind(fp) after the fgetc loop. Otherwise, you're already at EOF for the next loop.

Why do fscanf in the second loop instead of fgetc?

You don't add an EOS character at the end of each string.

Your second loop can be simplified. Note that you rely upon the fact that each line ends with '\n'. So, given that, you don't need to check against count in the second loop. You could add that as a cross check but it's really not [absolutely] necessary.

Here's a refactoring of the code:

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

#define K 10

int
main()
{
    int i,j;
    char c;
    int count=0;
    FILE *fp;

    fp = fopen("input1.txt","r");
    if (fp == NULL)
        printf("file not found\n");

    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n')
            count++;
    }

#if 1
    rewind(fp);
#endif

    char chz[count][K];

    i = 0;
    j = 0;

    while (1) {
        int chr = fgetc(fp);

        if (chr == EOF)
            break;

        // add EOS to "previous" word and start a new word
        if (chr == '\n') {
            chz[i][j] = 0;
            ++i;
            j = 0;
            continue;
        }

        // append char to word
        chz[i][j++] = chr;
    }

#if 0
    printf("%c",chz[0][1]);
#else
    for (i = 0;  i < count;  ++i)
        printf("WORD: '%s'\n",chz[i]);
#endif

    return 0;
}

You assume that the word length will never exceed K (i.e. K is fixed).

But, since you're looping through the file to calculate count, you can just as easily calculate the maximum value for K at the same time:

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

int
main()
{
    int i,j;
    char c;
    int count=0;
    FILE *fp;
    int len;
    int K = 0;

    fp = fopen("input1.txt","r");
    if (fp == NULL)
        printf("file not found\n");

    len = 0;
    while ((c = fgetc(fp)) != EOF) {
        if (c == '\n') {
            if (len > K)
                K = len;
            count++;
            len = 0;
        }
        else
            len++;
    }

#if 1
    rewind(fp);
#endif

    char chz[count][K + 1];

    i = 0;
    j = 0;

    while (1) {
        int chr = fgetc(fp);

        if (chr == EOF)
            break;

        // add EOS to "previous" word and start a new word
        if (chr == '\n') {
            chz[i][j] = 0;
            ++i;
            j = 0;
            continue;
        }

        // append char to word
        chz[i][j++] = chr;
    }

#if 0
    printf("%c",chz[0][1]);
#else
    for (i = 0;  i < count;  ++i)
        printf("WORD: '%s'\n",chz[i]);
#endif

    return 0;
}

UPDATE:

But I have one last problem. When I try to print this expression as chz [i][j] some words end up with meaningless signs like ^ +%. How can I prevent this?

You didn't post your code for this, but I suspect that you were using two nested loops, such as:

for (int i = 0;  i < count;  ++i) {
    for (int j = 0; j < K;  ++j)
        printf("%c",chz[i][j]);
    printf("\n");
}

Not all strings are the same (i.e. maximum) length. The probable reason is that, for strings that are shorter than K, you were outputting the extra [garbage] characters.

You need to stop at the length of each individual strings. Here's an adjusted set of loops to do that:

for (int i = 0;  i < count;  ++i) {
    int j = 0;

    while (1) {
        int chr = chz[i][j++];

        // stop at end of word
        if (chr == 0)
            break;

        putchar(chr);
    }

    putchar('\n');
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48
  • This is the perfect solution. Thank you very much. But I have one last problem. When I try to print this expression as chz [i] [j] some words end up with meaningless signs like ^ +%. How can I prevent this? – martinedenburg Nov 27 '20 at 23:38