0

I am new to C and I am confused how I can read through a file and store each line to an index of an array.

Example file:

What color is the sky?
Red
Orange
Yellow
Blue

Desired result of code:

input[0] = What color is the sky?
input[1] = Red
input[2] = Orange
input[3] = Yellow
input[4] = Blue

Hhere is what I have so far:

char input[60];

//declare string array of size 80, for 80 lines

for(int i = 0; fgets(input, sizeof(input), inFile)!=NULL; i++){ 

    //string[i] = input; storing this line to the string index

}

//later on use the string[80] that now has all lines

I understand that declaring input[60] is only determining the length of each line, not the number of lines. I am so used to thinking about strings in other coding languages, that the use of char is throwing me off. I have tried video tutorials but they didn't help me.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Alex Shaw
  • 11
  • 1
  • 3
  • Make `string` an array *of arrays* of characters, and use [`strcpy`](http://en.cppreference.com/w/c/string/byte/strcpy)? – Some programmer dude Sep 19 '18 at 05:32
  • Are you familiar with dynamic memory allocation via `malloc()` et al? If so, you could use that to make copies of the strings (lines) you read. If you've not covered `malloc()` and `free()` yet, then use the simpler but less flexible 2D array of characters. Don't forget to remove the newline that `fgets()` includes in the data. (Since you've got a comment about a string array of size 80 for 80 lines, what do you plan to write there? Why didn't you write it?) – Jonathan Leffler Sep 19 '18 at 05:45
  • is there a better method than `fgets()` ? and @JonathanLeffler, I didn't write it because I don't know the proper way to do it in C – Alex Shaw Sep 19 '18 at 05:49
  • Define "better"? Using [`fgets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) is using standard C and it is a good technique to use. There are grounds for considering POSIX [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) as better in some ways, but it isn't standard C (it is standard POSIX). It requires a slightly different approach — it allows a simpler approach to allocating the memory for your strings, but it requires knowledge which you probably don't yet have. – Jonathan Leffler Sep 19 '18 at 05:57
  • 1
    If you aren't sure how to declare a 2D array in C, it is difficult to help you without regurgitating what your text book should be telling you. We will help honest efforts to solve a problem, but we don't simply write the code for you. There are a number of ways that your problem could be tackled; we don't know which your course notes and lectures expect you to use. – Jonathan Leffler Sep 19 '18 at 05:59
  • well I know that if I do `char array[10][80]` that will make an array of size 10 where each index can hold 80 characters, correct? So if I want to store 80 lines of text and none of them are more than 70 characters long, I should make `char array[80][70]`. I like the idea of using `strcpy`, like @Someprogrammerdude suggested since I understand that function. So right now in my loop I'm trying `strcpy(array[i], input);` but that seems to be crashing the program. I appreciate your help! – Alex Shaw Sep 19 '18 at 06:06
  • 1
    Yes, using `char array[80][70];` would allow you to store up to 80 lines of up to 70 characters each, where the character count includes the terminating null byte (so up to 69 displayable characters and one null byte at the end). It's not obvious why `strcpy(array[i], input)` would crash your program unless you get more than 80 input lines. You should check that you don't go beyond the end of your array (that `i` does not reach or exceed 80). Please read about creating an MCVE ([MCVE]). That helps us to help you better. – Jonathan Leffler Sep 19 '18 at 06:15
  • bumping it from `char array[80][70]` to `char array[90][70]` did stop it from crashing. – Alex Shaw Sep 19 '18 at 06:20
  • heyyyyy I think i'm getting somewhere :D I am now using the 2D array to print some of the lines again. – Alex Shaw Sep 19 '18 at 06:24
  • YES! I was able to print out the entire document using the 2D array! – Alex Shaw Sep 19 '18 at 06:29
  • Even better duplicate I think: [C - how to store multiple strings in an array](https://stackoverflow.com/q/29568297/1025391) – moooeeeep Sep 19 '18 at 06:36
  • 1
    Thank you JonathanLeffler and @Some Programmer dude! I solved it with your guidance. – Alex Shaw Sep 19 '18 at 06:48

1 Answers1

-1

Each line of the file is a different string, and each string is a char* pointer to an array; so what you are needing is a 1D array of char* pointers (or alternately a 2D array of char.)

char *line[ MAX_LINES ];  // 1D array of char* pointers.

You can either initialize a two dimensional array of char, or you can malloc the memory for each line of the 1D char* pointers.

Here's an example of the malloc approach. The variable it's stored in is called "line" rather than "input"; but you can exchange the variable names if you like, and change the print formatting to solve your particular problem. This is just intended as an example of reading the strings into memory, in the same way you desire. No practical system has less than 4K of heap space, so I've omitted the malloc memory check.

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

#define MAX_LINES 10                                                            
#define MAX_LEN   60                                                            

int main( int narg, char *arg[] ) {                                             
    char input[ MAX_LEN ];                                                      
    char *line[ MAX_LINES ];                                                    
    FILE *inFile;                                                               
    int i,j;                                                                    

    if ( narg != 2 ){fprintf( stderr, "Use: %s filename\n", arg[0] ); return 2;}  
    if (!(inFile=fopen(arg[1],"r") )){
          fprintf( stderr, "Can't open '%s'\n",arg[1]);
          return 2;
    }

    for ( i=0; i<MAX_LINES && fgets(input, sizeof(input), inFile ); ++i ) {     
        int lineLen=strlen(input) + 1;                                          
        line[i] = strncpy( malloc( lineLen ), input, lineLen );                 
    }                                                                           

    for ( j=0; j<i; ++j ) { printf( "Line %d:%s", j+1, line[j] ); free(line[j]); }
    fclose(inFile);                                                             
    return 0;                                                                   
}        
  • 3
    The style indentation presented here is not OK, and would get you a "please explain" in any code review and/or programming assignment. – Kingsley Sep 19 '18 at 06:09
  • 1
    Please don't put multiple statements on a single line as you show; white space (newlines) are cheap, even on Stack Overflow. I observe that you include the newlines in the saved data. That's permissible and allows you to omit the newline at the end of the format string in the `printf()` statement You should check that `malloc()` succeeds before using it in `line[i] = strncpy( malloc( lineLen ), input, lineLen );`. While that may work most of the time in test programs, it is not safe for professional development work. – Jonathan Leffler Sep 19 '18 at 06:09
  • @kingsley; Yes, it would. But any C programmer KNOWS the meaning of curly braces, and short lines of 80 characters or less can be seen at a glance. The formatting is on purpose, for if the opening poster is copying this for homework, without understanding, they will get a penalty. If they are trying to "learn", about a specific detail ... they will write their own code for the homework assignment. – Andrew of Scappoose Sep 19 '18 at 06:29
  • `strlen`, `strncpy`, `malloc` and copy could be replaced by `strdup`... – Mathieu Sep 19 '18 at 07:36