C; storing strings in an array


 
Thread Tools Search this Thread
Top Forums Programming C; storing strings in an array
# 1  
Old 05-20-2012
C; storing strings in an array

I am trying to get userinput from stdin and store the lines in an array.


If i do this:
using a char **list to store strings
allocate memory to it
Code:
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
    char *prog = argv[0];
    
    char **linelist;
    int listlen = 3;
    int index = 0;

    char *line;
    int linelen = 80;
    int len = 0; 


    /*allocate memory*/
    /*****************/
    linelist = calloc(sizeof(char **), listlen);
    if (linelist == NULL) {
        fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                prog);
        exit(42);
    }

    line = malloc(linelen);
    if (line == NULL) {
        fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                prog);
    }

    /*fill it manually*/
    /******************/
    linelist[0] = "foo";
    linelist[1] = "bar";
    linelist[2] = "baz";


    /*print result on stdout, dummy*/
    /*******************************/
    for (index = 0; index < 3; ++index) {
        printf("%s\n", linelist[index]); 
    }

    
    return 0; 
}

it works. As far i see.

If i do this:
using a char **list
allocate memory to it
using getline to get input from stdin
allocate memory to each line:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char *prog = argv[0]; 
    
    char **linelist;
    int listlen = 3; 
    int index = 0; 

    char *line; 
    int linelen = 80; 
    int len = 0; 

    

    /*allocate memory*/
    /*****************/
    linelist = calloc(sizeof(char **), listlen); 
    if (linelist == NULL) {
        fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                prog); 
        exit(42); 
    }

    line = malloc(linelen); 
    if (line == NULL) {
        fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                prog); 
    }

    /*read input with getline*/
    /*************************/
    /* the former while  fails, lets check if the latter succeeds: well, kinda*/
    /*while (len = getline(&line, &linelen, stdin) && index < linelen -1 )   ) {*/
    while (index < listlen && (len = getline(&line, &linelen, stdin))   ) {
        /* debugging purpose*/    
        printf("size of line is: %d\n", len); 
        
        linelist[index] = malloc(len); 
        if (linelist[index] == NULL) {
            fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                    prog); 
        }

        linelist[index] = line;
        /*debugging purpose*/
        printf("line is: %s\n", linelist[index]); 
        /*gives correct output*/    
        ++index; 
    }

    /*result*/
    /********/
    /* both  gives wrong output,all give the last string entered on stdin*/
    for (index = 0; index < listlen -1; index++) {
        printf("element %d of linelist is: %s\n",  \
            index, linelist[index]); 
        }

    printf("%s\n", linelist[0]); 
    printf("%s\n", linelist[1]); 
    printf("%s\n", linelist[2]); 

    return 0; 
}

It fails.
What seems to get stored in the **list is three times the last input i get from stdin.
I don't understand why.

Here is the way i get the stdin as a standalone:
Code:
    while (index < listlen && (len = getline(&line, &linelen, stdin))   ) {
        /* debugging purpose*/    
        printf("size of line is: %d\n", len); 
        
        linelist[index] = malloc(len); 
        if (linelist[index] == NULL) {
            fprintf(stderr, "%s: Error. Could not allocate memory\n", \
                    prog); 
        }

        linelist[index] = line;
        /*debugging purpose*/
        printf("line is: %s\n", linelist[index]); 
        /*gives correct output*/    
        ++index; 
    }

printf("line is. %s\n", linelist[index]
gives the right string (the actual stdin). But it doesn't seem to get stored (correct) in "char **linelist".

thanks for a hint.
# 2  
Old 05-20-2012
Code:
linelist[index] = line;

line here is a pointer to something returned earlier. so you've set each element to point to the same place. you malloc enough for the string. you'd want to copy it with strcpy, or use strdup

Code:
strcpy(linelist[index],line);


Last edited by neutronscott; 05-20-2012 at 09:45 PM.. Reason: add code
This User Gave Thanks to neutronscott For This Post:
# 3  
Old 05-20-2012
Thanks. With
Code:
strcpy(linelist[index], line);


it works. But i think i had to add +1 to:
Code:
linelist[index] = malloc(len+1); 



I still fail to understand why.
To me it looks like the while loop reads one line at a time,
allocates memory to linelist[index],
then sets linelist[index] to be the line read with getline,
and increments index +1,
so that during the next run of the loop the next element of linelist will be set.
(Obviously it doesn't, but i can't see why).

# 4  
Old 05-20-2012
you merely set it to point to that same address each time. C has char type. a string is pointer (char *), so the variable itself is only memory location of the start. the end is when you hit a \0. so when you do line = malloc() you grab enough space for 79 chars and the null. getline writes to it, but it doesn't change the address.. that address stays the same here.

setting a pointer to a pointer only copies the address. you need to copy what's at the address. this requires a loop, continuing either a set length like with memcpy, or until null byte, strcpy.

pointers are sometimes a tough concept to fully grasp

edit: yes, the +1 to the malloc would be so you have room to store a \0 which is needed to terminate strings.
# 5  
Old 05-20-2012
Ok, thanks. I know in what direction to look.

I also found this and had some ideas (but like you say: it really can be hard to understand)

Using *retptr = p; in allocstr and &copystr in the caller, which showed me that i don't fully understand pointers yet.
# 6  
Old 05-21-2012
* means 'use an address as its contents', i.e. * for a type of char * would get you its first element, * for a type of int * would get you an integer, etc, etc.

& means 'turn a variable into an address'. & for a type of int would get you an int *, and so forth.

If you're still confused you'll have to start posting specific questions, because there's lots of stuff on that page.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Storing timestamp of files in an array

Hi, I have written the below script to get the timestamp of each files and result is as below Script find /home/user -type f -name "*.json" -printf '%Tc %p\n' | awk {'print $1 " " $2 " " $3 " " $4 " " $5 " " $6 " " $7'} Input -rw-r--r-- 1 user domain users 17382 Jul 19 06:10... (5 Replies)
Discussion started by: nextStep
5 Replies

2. Shell Programming and Scripting

Storing two dimensional array for postprocessing

Hi Community, Would love to get some quick help on below requirement. I am trying to process mpstat output from multiple blades of my server I would like to assign this the output to an array and then use it for post processing. How can I use a two dimensional array and assign these value ... (23 Replies)
Discussion started by: sshark
23 Replies

3. Shell Programming and Scripting

Storing command output in an array

Hi, I want keep/save one command's output in an array and later want to iterate over the array one by one for some processing. instead of doing like below- for str in `cat /etc/passwd | awk -F: '$3 >100 {print $1}' | uniq` want to store- my_array = `cat /etc/passwd | awk -F: '$3 >100 {print... (4 Replies)
Discussion started by: sanzee007
4 Replies

4. Shell Programming and Scripting

Storing data in perl 2D array

Respected All, Kindly help me out. I have got file listings in a directory like this: -rw-r--r-- 1 root root 115149 2011-11-17 07:15 file1.stat.log -rw-r--r-- 1 root root 115149 2011-11-18 08:15 file2.stat.log -rw-r--r-- 1 root root 115149 2011-11-19 09:15 file3.stat.log -rw-r--r-- 1... (2 Replies)
Discussion started by: teknokid1
2 Replies

5. UNIX for Dummies Questions & Answers

storing strings in C

i'm trying to figure out how to store strings into an array, can someone help me figure it out? i would like to store the following for example: array = "dog" array = "cat" the inputs are coming from the command line. Thanks, (6 Replies)
Discussion started by: l flipboi l
6 Replies

6. Shell Programming and Scripting

Storing blanks in an array in bash

Hi Guys, I have a file which is as follows: 1 2 4 6 7 I am trying to store these values in an array in bash. I have the following script: FILE=try.txt ARRAY=(`awk '{print}' $FILE`) echo ${ARRAY} (3 Replies)
Discussion started by: npatwardhan
3 Replies

7. Shell Programming and Scripting

storing values in a list or array

i have a file called file.txt having the following entries. 2321 2311 2313 4213 i wnat to store these values in a list and i want to iterate the list using loop and store it in another list (1 Reply)
Discussion started by: KiranKumarKarre
1 Replies

8. Shell Programming and Scripting

storing records in awk array

hi i have a file as follows: 1 2 3 4 5 6 i want to store all these numbers in an array using awk.. so far i have: awk '{for(i=1;i<=NR;i++) {a=$1}} END {for(i=1;i<=NR;i++) {printf("%1.11f",a)}}' 1.csv > test however, i am getting all values as zero in the "test" file..... (3 Replies)
Discussion started by: npatwardhan
3 Replies

9. Shell Programming and Scripting

storing variables in array.Please help

Hi All, I need some help with arrays. I need to take input from the user for hostname, username and password until he enters .(dot) or any other character and store the values in the variable array. I would further connect to the hostname using username and passwd and copy files from server to... (7 Replies)
Discussion started by: nua7
7 Replies

10. UNIX for Dummies Questions & Answers

Storing pointer array in C

All .. I am having a pointer array . And trying to store the addess into that pointer array . please see below the problem i faced code: int cnt1; char *t_array; char *f_array; for(cnt1=0; cnt1<1000; cnt1++) { t_array =... (1 Reply)
Discussion started by: arunkumar_mca
1 Replies
Login or Register to Ask a Question