Thread: Unexpected Printf Behavior

  1. #1
    Registered User
    Join Date
    Feb 2016
    Posts
    18

    Unexpected Printf Behavior

    Hey all, first post.

    I'm working on a program that does some basic file I/O. As of right now I'm just trying to read some integers from a text file into an array. In addition to enlightening me as to why my code is wrong, I am open to better implementations (although I chose this implementation as it is complicated and I want to fully grasp the fine-grained.... I understand that there most likely exists a much better way such as some fscanf loop).

    So the actual problem. Inside the main function, inside the while loop under the comment "read the numbers from a the file, ...", I am simply attempting to print out an integer array as a char array. But the printf statement only prints out the first digit of the string. I have examined the array contents at run-time with gdb and the contents are as expected.

    Example: With a file with a single line entry of "16", only the number 1 gets printed. Upon examination, the contents of the array is a[0] = 49, a[1] = 54, and a[2] = 0. I don't understand why printf won't print out the entire array.

    The code (note: i excluded erroneous code.... let me know if something is missing that you need to see):

    Code:
    int main(int argc, char *argv[])
    {
        /* TODO: Complete the main method according to the steps outlined */
    
    
        /* Open a file for reading */
        if(argc != 2){
            fprintf(stderr , "usage: %s [input file]" , argv[0]);
            exit(1);
        }
    
    
        FILE * fp;
        int i = 0, num_count = 0, len, num_list[MAX_INTS], buf[MAX_INT_LENGTH];
    
    
        if((fp = fopen(argv[1], "r")) == NULL){
            fprintf(stderr , "error: could not open file %s for reading" , argv[1]);
            exit(2);
        }
    
    
        /* Read the numbers from the file, into an array */
    
    
        while((len = fetch_line(buf, MAX_INT_LENGTH, fp)) > 0){
            // *(num_list + i++) = (int) strtol((char *)buf, NULL, DECIMAL);
            printf("%s\n", (char *)buf);
            num_count++;
        }
    
    int fetch_line( int * s , int limit , FILE * file_read ){
            int c , i;
            for( i = 0; i < limit - 1 && ( c = fgetc( file_read ) ) != NEWLINE && c != EOF; ++i )
                    s[ i ] = c;
            s[ i ] = '\0';
            return i;
    }

  2. #2
    Registered User
    Join Date
    Jun 2015
    Posts
    1,640
    Please post actual, complete code (including headers), preferably something you just ran and then copy/pasted. This code does not compile as it is missing headers and defines, and doesn't even have a complete main. You haven't even bothered to show an example input file.

    Anyway, your problem is simply that ints are not chars. How do you expect printf to print an int array as chars? Think about it. You read a char (1 byte) into an int (4 bytes). Most of the int's bytes will be 0. As soon as the printf hits one of those it considers the string to be ended and stops printing.

    Why are you reading chars into ints? Why are you trying to print them as chars? What are you actually trying to do?

  3. #3
    Registered User
    Join Date
    Feb 2016
    Posts
    18
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define MAX_INTS       1000
    #define MAX_INT_LENGTH 10
    #define DECIMAL        10
    #define NEWLINE           '\n'
    
    
    /* A node in the linked list */
    struct node {
        int data;
        struct node *next;
    };
    
    
    struct node* create_list(int intarray[], int len);
    
    
    struct node* add_item_at_start(struct node *head, int data);
    
    
    int search_array(int integers[], int numints, int element);
    
    
    int search_list(struct node *head, int element);
    
    
    struct node* create_sorted_list(struct node *head);
    
    
    struct node* add_item_sorted(struct node *head, int data);
    
    
    int copy_list_to_array(struct node *head, int *array);
    
    
    void print_list(struct node *head);
    
    
    void print_array(int integers[], int len);
    
    
    int fetch_line(int *, int, FILE *);
    
    
    int main(int argc, char *argv[])
    {
        /* TODO: Complete the main method according to the steps outlined */
    
    
        /* Open a file for reading */
        if(argc != 2){
            fprintf(stderr , "usage: %s [input file]" , argv[0]);
            exit(1);
        }
    
    
        FILE * fp;
        int i = 0, num_count = 0, len, num_list[MAX_INTS], buf[MAX_INT_LENGTH];
    
    
        if((fp = fopen(argv[1], "r")) == NULL){
            fprintf(stderr , "error: could not open file %s for reading" , argv[1]);
            exit(2);
        }
    
    
        /* Read the numbers from the file, into an array */
    
    
        while((len = fetch_line(buf, MAX_INT_LENGTH, fp)) > 0){
            // *(num_list + i++) = (int) strtol((char *)buf, NULL, DECIMAL);
            printf("%s\n", (char *)buf);
            num_count++;
        }
    
    
        /* Print the array */
    /*
        for(i = 0; i < num_count; i++)
            printf("List Entry %d -> %d\n" , i + 1, num_list[i]);
    */
        /* Create a linked list with the integers from the array */
        
        /* Print the linked list */
    
    
    
    
        /* Repeatedly prompt the user for a number to be searched.
        *  Search the array for the number and print out the result as shown in the specs.
        *  Search the linked list for the number and print out the result as shown in the specs.
        *  Stop prompting when the user enters 'q' (just the character q without the single quotes).
        */
    
    
        /* Create a sorted list(in ascending order) from the unsorted list */
    
    
        /* Print the sorted list */
    
    
        /* Copy the sorted list to an array with the same sorted order */
    
    
        /* Print out the sorted array */    
    
    
        /* Print the original linked list again */
    
    
        /* Print the original array again */
    
    
    
    
        /* Open a file for writing */
    
    
        /* Write the sorted array to a file named "sorted_numbers.txt" */
    
    
        /* Print out the number of integers written to the file */
    
    
    }
    
    
    struct node* create_list(int intarray[], int len)
    {
        struct node * head;
        int i;
    
    
        for(i = 0; i < len; i++ )
            head = add_item_at_start( head, *(intarray + i) );
    
    
        return head;
    }
    
    
    
    
    struct node* add_item_at_start(struct node *head, int data)
    {
        struct node * np = malloc( sizeof(struct node) );
        if(np == NULL)
            return head;
        np->data = data;
        np->next = head;
        return np;
    }
    
    
    int search_list(struct node *head, int element)
    {
        /* TODO: Complete this function */
    }
    
    
    int search_array(int integers[], int numints, int element)
    {
        int i;
        for(i = 0;i < numints; i++)
            if( *(integers + i) == element )
                return i;
        return -1;
    }
    
    
    int copy_list_to_array(struct node *head, int *array)
    {
        /* TODO: Complete this function */
    }
    
    
    struct node* create_sorted_list(struct node *head)
    {
        /* TODO: Complete this function */
    }
    
    
    struct node* add_item_sorted(struct node *sorted_head, int data)
    {
        /* TODO: Complete this function */
    }
    
    
    void print_list(struct node *head)
    {
        if (head == NULL) {
            printf("Linked List is Empty.\n");
        } else {
            struct node *temp = head;
            printf("head->");
            while (temp != NULL) {
                printf("|%d|->", temp->data);
                temp = temp->next;
            }
            printf("NULL\n");
        }
    }
    
    
    void print_array(int integers[], int len)
    {
        int i;
        for (i = 0; i < len; i++) {
            printf("| %d ", integers[i]);
        }
        printf("|\n");
    }
    
    
    int fetch_line( int * s , int limit , FILE * file_read ){
            int c , i;
            for( i = 0; i < limit - 1 && ( c = fgetc( file_read ) ) != NEWLINE && c != EOF; ++i )
                    s[ i ] = c;
            s[ i ] = '\0';
            return i;
    }
    Here is an example input file.

    Code:
    16
    My thought was that casting the int * to a char * forces the compiler to interpret the entries as chars and not integers. I know that in C, chars are often stored in int variables in order to deal with EOF properly.

    I'm working on a homework assignment.

  4. #4
    Registered User
    Join Date
    Feb 2016
    Posts
    18
    Found the problem.... I was reusing the fetch_line function that I had modified for something else. The array to store the number(buf) as characters should be a char *, not an int * as pointed out above (thanks!).

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by John...
    My thought was that casting the int * to a char * forces the compiler to interpret the entries as chars and not integers.
    That is true. However, this is usually only used when you want to access the bytes of the int that the char* would point to. Such a sequence of bytes does not necessarily constitute a null terminated string, so it would be incorrect to use printf with %s to print them.

    Quote Originally Posted by John...
    I know that in C, chars are often stored in int variables in order to deal with EOF properly.
    Not quite: there are a number of input functions that return a character, converted to unsigned char, as an int. This is indeed so that these functions can also return EOF. However, this does not mean that all character input must be done via int. So, it looks like you want to read a line, and this line will presumably be stored as a null terminated string. Therefore, you should have an array of char, not an array of int, to store the line.

    So, when you call fgetc, you should store the return value in an int because you need to account for EOF. But once you are sure that the return value is not EOF, you can then write it to the char element of the array.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. unexpected behavior of std::current_exception()
    By Elkvis in forum C++ Programming
    Replies: 5
    Last Post: 01-25-2013, 03:37 PM
  2. Odd printf behavior?
    By tallen387 in forum C Programming
    Replies: 4
    Last Post: 04-10-2011, 08:35 AM
  3. Unexpected behavior of stdarg
    By fredb in forum C Programming
    Replies: 2
    Last Post: 01-23-2011, 05:01 AM
  4. scanf/printf unexpected behavior
    By DanV2 in forum C Programming
    Replies: 2
    Last Post: 10-11-2010, 10:23 AM
  5. Behavior of printf
    By sewilli in forum C Programming
    Replies: 2
    Last Post: 11-13-2002, 01:40 AM