开发者

Issue with printing char *argv[n] after a function call in C

开发者 https://www.devze.com 2023-01-27 13:50 出处:网络
int readOptions(char *argv[]){ FILE * infile; char line_buf[BUFSIZ]; int i = 0, j = 0 ; infile = fopen(\"options\",\"r\");
int readOptions(char *argv[]){
        FILE * infile;
        char line_buf[BUFSIZ];
        int i = 0, j = 0 ; 
        infile = fopen("options","r");
            if(!infile){

                     fprintf(stderr,"File Read failure\n");
                        exit(2);
            }

        while( i < 10 && fgets(line_buf,sizeof(line_buf),infile)!=0){

             printf("Line buf : %s",line_buf); 
             argv[i] =  line_buf;                                   

             i++;                               
}

}

int main(){

int j ; 

char *options[10];开发者_StackOverflow社区 

for(j = 0 ; j< 10 ; j++){

        options[j] = malloc(len * sizeof (char));
    } 

 readOptions(options);
for(j=0; j<10 ; j++)
         printf("%s %d\n",options[j], j );

}

The problem is that I always see - the program print only the last line read in the file. Where is the mistake ? and am I missing any important pointer concept with this code ?


Every element of argv points to the same line_buf. Use strdup() to create new strings instead (which you will later have to free).


A char* is not a string. It is a pointer. In your loop, you set each char* in your char*[] to point at the beginning of the line_buf array. Thus, each refers to the same data (which, furthermore, is no longer available after returning from the function; you get undefined behaviour at this point and you're just "lucky" - actually very unlucky, because it makes it harder to diagnose the problem - that it seems to "work" as well as it does.)

There is no real string type in C. You must set up separate chunks of memory that will hold the characters, and point at those chunks. If you allocate them dynamically, you will also have to free them. If you want to be able to resize them, or in general handle things of unknown size, that's also on you.

You've written the code to allocate some space, but you don't copy the data into the space - instead, you repoint the pointers at the local buffer. As noted, we use strcpy to copy from one buffer to another. But there's no real point in doing that, if you're going to pass in allocated buffers and limit yourself to their sizes anyway; instead, just fgets directly into the buffers pointed at by the pointers in the argv array, instead of into a local one.


The argv[i]s are not strings in and of themselves, but pointers to areas of memory that contain text strings. That's what you're doing when you say options[j] = malloc(...) -- you're setting aside an area of memory for that pointer to point at. But that area of memory is just an area of memory, it doesn't have anything to do with the pointer, except that the pointer happens to be pointing at it.

So when you say argv[i] = line_buf, that doesn't mean copy the string itself. It means change the pointer, such that argv[i] now points to the same area of memory where line_buf[] starts. Then in the next iteration of your for loop, you overwrite that same area of memory. By the end of the loop, all ten of your pointers are pointing to line_buf, which contains the last line of your file, which is why you get ten copies of that line.

(What's also worth noting is that once readOptions() returns, that area of memory that all your pointers are pointing to is considered undefined, because line_buf[] only "exists" within the readOptions() function. It's only through luck that your program is printing the last line ten times, rather than printing garbage or crashing.)

Now, to copy a string from one place to another, you can use the strcpy() function, which can be added to your program by putting #include <string.h> at the top. You'd then write strcpy(argv[i], line_buf).

Here's what a simple version of strcpy() would look like, so you can see what it's doing:

char *strcpy(char *dest, char *source) {
    int i = 0;
    while (source[i] != '\0') {  /* a zero (or "null") byte means end of string */
        dest[i] = source[i];
        i=i+1;
    }
    dest[i] = source[i];
    return dest;
}

Notice that strcpy() doesn't have any way of knowing how much space there is to copy into! If you don't have enough space available, it will go right past the end of your space and into who knows what memory areas, which may cause your program to crash or behave strangely. This is called a buffer overrun, and it's one of the most common security errors. So make sure you have enough space before you call strcpy().

0

精彩评论

暂无评论...
验证码 换一张
取 消