You know how to use 1D arrays, right? 2D arrays are 1D arrays where every item is an array. C has arrays of arrays instead of true multidimensional arrays:
int a[5] = {1,2,3,4,5};
[0] -> [1][2][3][4][5]
int b[3][2] =
{
{1, 2},
{3, 4},
{5, 6}
};
[0] -> [1][2]
[1] -> [3][4]
[2] -> [5][6] #include <stdio.h>
#define ASIZE 5
#define BXSIZE 3
#define BYSIZE 2
int main()
{
int a[ASIZE] = {1,2,3,4,5};
int b[BXSIZE][BYSIZE] =
{
{1, 2},
{3, 4},
{5, 6}
};
int x, y;
for (x = 0; x < ASIZE; ++x)
{
printf("%d%s", a[x], x < ASIZE - 1 ? " " : "\n");
}
for (x = 0; x < BXSIZE; ++x)
{
for (y = 0; y < BYSIZE; ++y)
{
printf("%d%s", b[x][y], y < BYSIZE - 1 ? " " : "\n");
}
}
return 0;
} A string variable is a char array, right? So an array of strings is an array of char arrays, and instead of using name to get the string variable, you use name[x] . Everything else is the same:
#include <stdio.h>
#include <string.h>
#define NAME_CNT 5
#define NAME_LEN 20
int main()
{
/* 5 names up to 19 chars each */
char name[NAME_CNT][NAME_LEN];
size_t x, y, n;
printf("Enter %d names\n", NAME_CNT);
for (x = 0; x < NAME_CNT; ++x)
{
printf("Name #%d: ", x + 1);
fflush(stdout);
if (!fgets(name[x], NAME_LEN, stdin)) break;
/* trim any trailing line break */
n = strlen(name[x]);
if (name[x][n-1] == '\n') name[x][n-1] = '\0';
}
for (y = 0; y < x; ++y) puts(name[y]);
return 0;
} spopen = fopen ("list.txt", "r"); while ( (fscanf (spopen, "%s", &name)) != EOF)
Do not forget to check that fopen() succeeded. If it did not, it returns a null pointer and your program will probably crash without any warning or hint as to what happened:
spopen = fopen("list.txt", "r");
if (!spopen)
{
perror("opening list.txt");
/* exit or recover */
} And do not forget to close the file when you are done with it. ;)
while ( (fscanf (spopen, "%s", &name)) != EOF)
fscanf() does return EOF at the right time for this loop, so the code is right. But I think it is a better habit to use the number of conversions for the test instead of EOF directly. If you expect 1 conversion and fscanf() returns EOF, the loop will stop as it should. But if the stream gets corrupted somehow and instead of EOF, no conversions are made and fscanf() returns 0, the loop will not stop as it should. Using the expected conversions for the test works in both cases.
Another small nitpick is that name is already a char pointer and that is what fscanf expects. Used as a value, array names decay into a pointer to the first item. When you say &name , it adds a level of indirection and the type changes to a pointer to a char array. Mismatching types in fscanf() is undefined behavior:
while (fscanf(spopen, "%s", name) == 1)
{
printf ("%s\n", name);
}
if (ferror(spopen))
{
perror("spopen stream state");
/* exit or recover */
}
fclose(spopen);