Thread: character strings and reading in a file...

  1. #1
    Unregistered
    Guest

    character strings and reading in a file...

    if anyone could help me and tell me what's wrong or give me some hints...

    I am trying to read in a file called "data" using a function called "readfile", but I keep getting "segmentation fault (core dumped)" when I run my program.

    Here is my code (I have commented out some parts of it because I just want to get the reading in a file working first):

    #include <stdio.h>
    #include <string.h>
    #define SIZE 100

    int readfile(char *filename, char *names [], int numbers [] );
    /*void nametoupper(char name [] );
    void sortbyname(char *names [], int numbers [], int size );
    void sortbynumber(char *names [], int numbers [], int size );
    void swap(char *string1, char *string2);
    void printall(char *names [], int numbers [], int size );
    */
    int main ()
    {
    char *filename;
    char *names [50];
    int name;
    int numbers [SIZE];

    printf("Type the name of the file to be sorted:\n");
    scanf("%s", filename);

    readfile(filename, names, numbers);
    /*nametoupper( names );
    sortbyname( names, numbers, size );
    printall( names, numbers, size );

    printf("Press any key to continue:\n");
    getchar ();
    sortbynumber( names, numbers, size );
    printall( names, numbers, size );
    */
    return 0;
    }

    Here is the readfile function code:
    #include <stdio.h>
    #include <stdlib.h>

    int parseline(const char *text, char **name, int *num);

    int readfile(const char *filename, char *names[], int numbers[])
    {

    FILE *fp;
    char textline[256];
    char *status;
    int countlines = 0;
    int len;
    int linestat;

    /* Try to open the file, bail out if it can't be done */
    fp = fopen(filename,"r");
    if (fp == NULL) {
    fprintf(stderr,"Unable to open file %s\n",filename);
    exit(1);
    }

    status = fgets(textline, 255, fp);
    while (status != NULL) {
    len = strlen(textline);
    if (textline[len-1] == '\n') {
    textline[len-1] = '\0';
    }
    linestat = parseline(textline,&(names[countlines]),&(numbers[countlines]));
    if (linestat != -1) {
    countlines += 1;
    }
    status = fgets(textline, 255, fp);
    }

    return(countlines);
    }

    int parseline(const char *text, char **name, int *num) {

    int last;
    int index;

    last = strlen(text) - 1;
    index = last;
    while ((isspace(text[index])) && (index >= 0)) {
    index -= 1;
    }
    while ((isdigit(text[index])) && (index >= 0)) {
    index -= 1;
    }

    if ((index > 0) && (index < last)) {
    *num = atoi(&(text[index+1]));
    *name = (char *) malloc((index+2)*sizeof(char));
    strncpy(*name,text,index+1);
    (*name)[index+1] = '\0';
    return 0;
    } else {
    fprintf(stderr,"Warning: this line is not in the right format\n %s\n",text);
    return -1;
    }
    }

    And here is the "data" I want to input as the filename to be sorted:

    Chad Lewis 15
    Sean Lowe 23
    Harold Dane 46
    Sam Zane 34
    Shiki Lars 89


    If anyone could help me....

    Thanks,
    Newbie

  2. #2
    Registered User
    Join Date
    Jul 2002
    Posts
    13
    char *names [50];

    This line creates an array of 50 pointers. It does NOT allocate the memory for those pointers. So when you tried to write to them, you accessed protected memory and crashed. Add these lines before your call to readline:

    Code:
    int x;
    for(x=0;x<50;x++){
       names[x]=malloc(256*sizeof(char));
       if(names[x]==NULL){
          return 0;  /*error*/
        }
    }
    Note that even this is not safe- if there are more than 50 lines in the file, or if there are fewer, but lines are over 255 characters. A safer way would be to make either:

    1)Low flexibility: readfile take a max # of lines, and dump any overage. This can be a max defined by readfile, or taken as a parameter.

    2)Medium flexibility: Write a function to count the number of lines, and return the size of the file. Make names a char **,. and allocate the needed number of pointers, then allocate each line pointer.

    3)Max flexibility: Make 2 new functions. Function 1 gets file length in lines, function 2 gets the length of each line, so no lines over 255 chars are wrapped. Function 3 will write to buffers for each line. Using this method you can minimize memory waste and eliminate any chance of problems. It is the slowest, however.

  3. #3
    Unregistered
    Guest
    Thanks for the explanation and the info, but I am still getting a segementation fault error....

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    So post your new code. And remember. Use code tags:

    [code]
    ... your code here ...
    [/code]

    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Jul 2002
    Posts
    13
    Or I could be a complete moron and miss your real problem completely.

    Code:
    char *filename;
    char *names [50];
    int name;
    int numbers [SIZE];
    
    printf("Type the name of the file to be sorted:\n");
    scanf("%s", filename);

    You never allocated space for filename. Either malloc it some memory, or use an array instead.

    Also, its considered very odd and poor style for a function to return dynamically allocated memory to the caller, like you do in parseline. The reason being that people will frequently forget to free the memory, causing a leak. It also makes the cause of error difficult to track down, as you don't know who the owner is. The normal method is to pass memory down to the called functions.

  6. #6
    Unregistered
    Guest
    Here is my current code:
    ---------------------------------------------------------------------------------
    #include <stdio.h>
    #include <string.h>
    #define SIZE 100

    int readfile(char *filename, char *names [], int numbers [] );
    /*void nametoupper(char name [] );
    void sortbyname(char *names [], int numbers [], int size );
    void sortbynumber(char *names [], int numbers [], int size );
    void swap(char *string1, char *string2);
    void printall(char *names [], int numbers [], int size );
    */
    int main ()
    {
    char *filename;
    char *names;
    int name;
    int numbers [SIZE];
    int x;

    printf("Type the name of the file to be sorted:\n");
    scanf("%s", filename);

    for(x=0;x<50;x++){
    names[x]=malloc(256*sizeof(char));
    if(names[x]==NULL){
    return 0; /*error*/
    }
    }
    readfile(filename, names, numbers);
    /*nametoupper( names );
    sortbyname( names, numbers, SIZE );
    printall( names, numbers, SIZE );

    printf("Press any key to continue:\n");
    getchar ();

    sortbynumber( names, numbers, SIZE );
    printall( names, numbers, SIZE );
    */
    return 0;
    }
    ----------------------------------------------------------------------------------

  7. #7
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Take a gander at Javariel's reply. Then take a look at mine, which shows how to use code tags.

    Quzah.
    Hope is the first step on the road to disappointment.

  8. #8
    Unregistered
    Guest
    Sorry about the code tags...I am new to this forum....

    I tried allocating space to both filename and names using Javariel's method....but I still get a segmentation fault. We have just started to learn about pointers in class, so bare with me I am just a beginner.

    This is what I tried:

    Code:
     
    #include <stdio.h>
    #include <string.h>
    #define SIZE 100
    
    int readfile(char *filename, char *names [], int numbers [] );
    /*void nametoupper(char name [] );
    void sortbyname(char *names [], int numbers [], int size );
    void sortbynumber(char *names [], int numbers [], int size );
    void swap(char *string1, char *string2);
    void printall(char *names [], int numbers [], int size );
    */
    int main ()
    {
    char *filename;
    char *names;
    int name;
    int numbers [SIZE];
    int x, y;
    
    printf("Type the name of the file to be sorted:\n");
    scanf("%s", filename);
    
    for(x=0;x<50;x++){
       names[x]=malloc(256*sizeof(char));
       if(names[x]==NULL){
          return 0;  /*error*/
        }
    }
    for(y=0;y<50;y++){
       filename[y]=malloc(256*sizeof(char));
       if(filename[y]==NULL){
          return 0;  /*error*/
        }
    }
    
    
    readfile(filename, names, numbers);
    /*nametoupper( names );
    sortbyname( names, numbers, SIZE );
    printall( names, numbers, SIZE );
     
    printf("Press any key to continue:\n");
    getchar (); 
    
    sortbynumber( names, numbers, SIZE );
    printall( names, numbers, SIZE );
    */
    return 0;
    }

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    char *filename;
    char *names;
    int name;
    int numbers [SIZE];
    int x, y;
    
    printf("Type the name of the file to be sorted:\n");
    scanf("%s", filename);
    You still have no space allocated for the file name. Try something like:

    char filename[BUFSIZ];

    ... stuff here ...

    printf("Type the name of the file to be sorted:\n");
    fgets( filename, BUFSIZ, stdin );
    filename[strlen(filename)-1] = '\0';

    That should do the trick. fgets is a safe way to read strings. It will only read "one less than the size you indicate" characters, and it will add a null to the end. The only thing to remember is that if you have a newline (return) on the end of the string, you'll want to snip it off. That's what the last line of code does.

    'stdin' is the standard input file stream, or in other words, the keyboard. Since I used 'f'-gets, I needed to specify a file to read from. On a side note, never just use 'gets'. It's unsafe.

    Quzah.
    Hope is the first step on the road to disappointment.

  10. #10
    Unregistered
    Guest
    Thanks for your help quzah, but even with the changes from your suggestions, I still get a segmentation fault....and this warning warning: passing arg 2 of `readfile' from incompatible pointer type

    This is what I tried:
    Code:
     
    
    #include <stdio.h>
    #include <string.h>
    #define SIZE 100
    #define BUFSIZ 50
    
    int readfile(char *filename, char *names [], int numbers [] );
    /*void nametoupper(char name [] );
    void sortbyname(char *names [], int numbers [], int size );
    void sortbynumber(char *names [], int numbers [], int size );
    void swap(char *string1, char *string2);
    void printall(char *names [], int numbers [], int size );
    */
    int main ()
    {
    
    char filename[BUFSIZ];
    char *names;
    int name;
    int numbers [SIZE];
    int x;
    
    printf("Type the name of the file to be sorted:\n");
    fgets( filename, BUFSIZ, stdin );
    filename[strlen(filename)-1] = '\0';
    
    for(x=0;x<50;x++){
       names[x]=malloc(256*sizeof(char));
       if(names[x]==NULL){
          return 0;  /*error*/
      }
    }
    
    readfile(filename, names, numbers);
    /*nametoupper( names );
    sortbyname( names, numbers, SIZE );
    printall( names, numbers, SIZE ); 
    
    printf("Press any key to continue:\n");
    getchar ();
    
    sortbynumber( names, numbers, SIZE );
    printall( names, numbers, SIZE );
    */
    return 0;
    }

  11. #11
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    That's because you're not passing it correct arguments:

    int readfile(char *filename, char *names [], int numbers [] );


    And you pass it:

    char *names;


    You need an array of character poitners, not just a character pointer.

    char *names[SOMENUMBER];

    That'll fix it.

    Quzah.
    Hope is the first step on the road to disappointment.

  12. #12
    Unregistered
    Guest
    Thanks Quzah, it works now...I can finally read in a file.

    Now if I could only get my other functions to work. *L*
    My professor did say pointers could be a nightmare....

  13. #13
    Unregistered
    Guest
    Hi again,

    I was wrong...it didn't exactly work. Now I am getting the segmentating fault error again. If anyone could help me again.... It compiles with no errors and no warnings....but I am thinking it is a pointer problem... I am so lost.

    Here is what I have now:
    [code]
    #include <stdio.h>
    #include <string.h>
    #define SIZE 100

    /*function prototypes*/
    /*int readfile(char *filename, char *names [], int numbers [] );
    void nametoupper(char *names [] );
    void sortbyname(char *names [], int numbers [], int size );
    void sortbynumber(char *names [], int numbers [], int size );
    void swap(char *string1, char *string2);
    void printall(char *names [], int numbers [], int size );
    */
    int main ()
    {

    /*declaration of variables*/
    char filename [BUFSIZ];
    char *names [SIZE];
    int name;
    int numbers [SIZE];

    /*prompt user for filename*/
    printf("Type the name of the file to be sorted:\n");

    /*read in filename*/
    fgets( filename, BUFSIZ, stdin );

    filename[strlen(filename)-1] = '\0';
    /*call functions*/
    readfile(filename, names, numbers);
    /*nametoupper(names );
    sortbyname( names, numbers, SIZE );
    printall( names, numbers, SIZE );

    /*pause in the program*/
    printf("Press any key to continue:\n");
    getchar ();

    sortbynumber( names, numbers, SIZE );
    printall( names, numbers, SIZE );
    */
    return 0;
    } /*end main*/

  14. #14
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Is this all of your code? Because you can't call functions that don't have a definition.

    -Prelude
    My best code is written with the delete key.

  15. #15
    Unregistered
    Guest
    sorry ... I didn't post all of my code with the definitons of the other functions. I have commented out the other functions because I just want to get reading in a file to work first.

    the readfile code is in my first post... It is a separate file, that I link with my main code to compile.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading Multiple Multi-Part Strings From a Text File
    By bengreenwood in forum C++ Programming
    Replies: 2
    Last Post: 06-02-2009, 10:43 AM
  2. reading from a file + list of strings
    By stewie1986 in forum C Programming
    Replies: 2
    Last Post: 12-06-2007, 11:59 PM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. question about reading in strings from a file :>
    By bball887 in forum C Programming
    Replies: 8
    Last Post: 04-13-2004, 06:24 PM
  5. Reading strings from a file
    By Capulet in forum C Programming
    Replies: 7
    Last Post: 12-04-2002, 04:58 AM