#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    1
    Rep Power
    0

    Phone number C Program


    Hello, I am a beginning C programmer and I am stuck on a question that our teacher gave us. We are suppose to have a file that inputs a .txt file with 2 names and phone numbers. The end result should look like this:

    Clayton xxx-xxx-xxxx
    Jonathan xxx-xxx-xxxx (there are actual numbers where there are x's)

    Here is the code I have so far:

    **********************
    #include <stdio.h>
    main() {
    struct telephone {
    char name[80];
    long long int number;
    };

    int n;
    int i;
    int c;

    FILE *tele;
    tele = fopen("phone.txt","r");
    fscanf(tele, " %d",&n);
    printf("The number of name/phone number pairs is %d\n",n);

    struct telephone a[n];
    for (i =0; i < n; i++){
    fscanf(tele, " %s %lld", a[i].name,&a[i].number);
    printf("%s %lld\n",a[i].name,a[i].number);
    }

    struct telephone swap;

    for(c = 0; c < (n-1); c++) {

    for(i = 0; i < (c-n-1); i++) {

    if (a[i].number < a[i+1].number) {
    swap = a[i];
    a[i] = a[i+1];
    a[i+1] = swap;
    }
    }
    }

    printf("%s %lld\n",printNumber(g[h]));
    fclose(tele);
    return(0);
    }
    void printNumber(long long int f){
    int g[10], h;
    for(h = 9; h >= 0; h--){
    g[h] = f % 10;
    f /= 10;
    }
    printf("%d%d%d-%d%d%d-%d%d%d%d ", g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9]);
    }
    *******************
    I know I need a for loop before the second to last printf statement. I also know that for that printf statement I need to call the printNumber function. I just don't know how to implement this. Any help would be great!!
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,841
    Rep Power
    480
    What does the input look like and why bother reading the phone number as a number? Would it not be simpler to treat it as characters throughout the program?
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    First mistake: You did not use code tags to preserve your code's indenting. As a result, it's an unreadable mess.

    Here is your code with code tags; your original indenting was recovered via the Reply button:

    Code:
    #include <stdio.h>
    main() {
      struct telephone {
      char name[80];
      long long int number;
      };
    
     int n;
     int i;
     int c;
    
      FILE *tele;
      tele = fopen("phone.txt","r");
      fscanf(tele, " %d",&n);
      printf("The number of name/phone number pairs is  %d\n",n);
    
      struct telephone a[n];
        for (i =0; i < n; i++){
        fscanf(tele, " %s %lld", a[i].name,&a[i].number);
        printf("%s %lld\n",a[i].name,a[i].number);
        }
    
      struct telephone swap;
    
             for(c = 0; c < (n-1); c++) {
    
                    for(i = 0; i < (c-n-1); i++) {
    
                            if (a[i].number < a[i+1].number) {
                                     swap   = a[i];
                                     a[i]   = a[i+1];
                                     a[i+1] = swap;
                            }
                    }
            }
    
            printf("%s %lld\n",printNumber(g[h]));
     fclose(tele);
     return(0);
    }
    void printNumber(long long int f){
     int g[10], h;
     for(h = 9; h >= 0; h--){
      g[h] = f % 10;
      f /= 10;
     }
     printf("%d%d%d-%d%d%d-%d%d%d%d ", g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9]);
    }
    Your second mistake: Inconsistent indenting. This mistake is compounded by your use of K&R indent style, which depends absolutely on consistent indenting. Instead, you should use a better style that will make your code readable, such as the Allman style. Since not only others but also you yourself need to be able to read and understand your code, readability is of the utmost importance. At least with the Allman style your code can still retain some readability when you get sloppy again with your indenting.

    Here is your code properly formatted:
    Code:
    #include <stdio.h>
    
    main() 
    {
        struct telephone 
        {
            char name[80];
            long long int number;
        };
    
        int n;
        int i;
        int c;
    
        FILE *tele;
        tele = fopen("phone.txt","r");
        fscanf(tele, " %d",&n);
        printf("The number of name/phone number pairs is  %d\n",n);
    
        struct telephone a[n];
        
        for (i =0; i < n; i++)
        {
            fscanf(tele, " %s %lld", a[i].name,&a[i].number);
            printf("%s %lld\n",a[i].name,a[i].number);
        }
    
        struct telephone swap;
    
        for(c = 0; c < (n-1); c++) 
        {
            for(i = 0; i < (c-n-1); i++) 
            {
                if (a[i].number < a[i+1].number) 
                {
                    swap   = a[i];
                    a[i]   = a[i+1];
                    a[i+1] = swap;
                }
            }
        }
    
        printf("%s %lld\n",printNumber(g[h]));
        fclose(tele);
        return(0);
    }
    
    void printNumber(long long int f)
    {
        int g[10], h;
        
        for(h = 9; h >= 0; h--)
        {
            g[h] = f % 10;
            f /= 10;
        }
        printf("%d%d%d-%d%d%d-%d%d%d%d ", g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9]);
    }
    Your third mistake: Your code does not compile and you have made no attempt to correct those errors and warnings. Here is what I get when I try to compile it (MinGW gcc on WinXP; line numbers correspond to my reformatting of your code):
    C:TEST>gcc -Wall begincoder1.c
    begincoder1.c
    begincoder1.c:4: warning: return-type defaults to `int'
    begincoder1.c: In function `main':
    begincoder1.c:20: parse error before `struct'
    begincoder1.c:24: `a' undeclared (first use in this function)
    begincoder1.c:24: (Each undeclared identifier is reported only once
    begincoder1.c:24: for each function it appears in.)
    begincoder1.c:28: parse error before `struct'
    begincoder1.c:36: `swap' undeclared (first use in this function)
    begincoder1.c:43: warning: implicit declaration of function `printNumber'
    begincoder1.c:43: `g' undeclared (first use in this function)
    begincoder1.c:43: `h' undeclared (first use in this function)
    begincoder1.c:43: warning: format argument is not a pointer (arg 2)
    begincoder1.c:43: warning: too few arguments for format
    begincoder1.c: At top level:
    begincoder1.c:49: warning: type mismatch with previous implicit declaration
    begincoder1.c:43: warning: previous implicit declaration of `printNumber'
    begincoder1.c:49: warning: `printNumber' was previously implicitly declared to return `int'

    C:TEST>
    Are you ignoring errors and warnings? Never ignore warnings! Don't even begin to think of trying to run your program until you have cleaned up all warnings!

    main returns an int, so then say so explicitly. Never use implicit declarations.

    You are intermingling declarations with your code. C does not allow that, though C++ and C99 do. All your declarations need to be up at the beginning of the block. If you are using C99, then why did it allow you to implicitly declare main as int? From what I've read, C99 doesn't allow implicit declarations.

    Why are you using the FILE*, tele, without testing whether file opened successfully? If fopen fails, then it returns NULL. Trying to use a NULL tele would cause your program to crash. Always test the return value of fopen. Never try to use a NULL FILE*.


    You call the function, printNumber, without telling the compiler anything about it. That's what caused these warnings:
    begincoder1.c:43: warning: implicit declaration of function `printNumber'
    begincoder1.c:49: warning: type mismatch with previous implicit declaration
    begincoder1.c:43: warning: previous implicit declaration of `printNumber'
    begincoder1.c:49: warning: `printNumber' was previously implicitly declared to return `int'
    You need to place a prototype for printNumber up above main.

    This line of code:
    Code:
        printf("%s %lld\n",printNumber(g[h]));
    generated these diagnostics:
    begincoder1.c:43: warning: implicit declaration of function `printNumber'
    begincoder1.c:43: `g' undeclared (first use in this function)
    begincoder1.c:43: `h' undeclared (first use in this function)
    begincoder1.c:43: warning: format argument is not a pointer (arg 2)
    begincoder1.c:43: warning: too few arguments for format
    You already understand the first warning. The next two errors are because you never declared g nor h in main. You have to declare and initialize a variable before you can use it; not even C99 will let you get away with that!

    Now skip down to the last warning, "too few arguments for format". You told printf that you would give it two arguments, a string and an long long int. You only gave it one argument (and a void one at that! -- double howler!). printf is going to use the first argument as a string (good luck on that one!) and then it's going to look where it would have expected a second argument to be and it's going to read whatever garbage it finds there and it will display that. As a result, you would come running back here whining about how your printf displayed this weird garbage. Well, you lied to the compiler and it got its revenge. Never lie to the compiler!

    But that "string" argument you gave isn't a string -- "warning: format argument is not a pointer (arg 2)". For that matter, it isn't anything at all! printNumber is a void function. That means that it does not return any value! And you are feeding that non-existent value to printf as the memory address of a string! To be honest, I have absolutely no idea what kind of code the compile would generate for that howler, but I'm pretty certain that by hook or by crook printf would have come up with a memory address and that it would most certainly be pure garbage and that the result would either be a monumental program crash or a long stream of pure garbage characters.

    Correct your code. Recompile it with warnings turned on and up! Keep correcting and recompiling until it compiles cleanly, meaning no errors and no warnings. Only then can you try to run it.

    Never ignore warnings! Warnings are so much more important than error messages. Never ignore warnings!
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    I agree with b49P23TIvg:
    Originally Posted by b49P23TIvg
    ... and why bother reading the phone number as a number? Would it not be simpler to treat it as characters throughout the program?
    Besides the obvious question of "what purpose does converting that to a number serve?", there's also the issue of your fscanf not doing what you expect it to do:
    Code:
            fscanf(tele, " %s %lld", a[i].name,&a[i].number);
    Consider the format of that file as you described it to us (with me changing the phone number fields so we can distinguish them from each other):
    Originally Posted by BeginCoder
    Clayton xxx-yyy-zzzz
    Jonathan aaa-bbb-cccc (there are actual numbers where there are x's)
    The first fscanf would read in Clayton and xxx, leaving -yyy-zzzz to be read by the later calls. The next call would make the name "-yyy-zzzz" and would not change the number field because it would fail to interpret "Jonathan" as a number. And if you have more lines, then you'd have name fields loaded with the complete telephone numbers and number fields left with garbage in them because none of the names would qualify as numbers.

    Rather, you would need something like:
    Code:
            fscanf(tele, " %s %d-%d-%d", a[i].name,&a[i].number[0],
                    &a[i].number[1],&a[i].number[2]);
    IOW, you'd have to tell fscanf to expect those hyphens between the digits and to read in the groupings of digits separately. Write a test program so you can play with that using scanf so you can vary what you type in at the keyboard and have the test program print out what you had input. Little test programs like that are good for proving out parts of your larger program.

    Also, if the name is more than one word (delimited by spaces; eg, "De Forest", the first name of the actor who played Dr. McCoy), then you'd have a problem there too.

IMN logo majestic logo threadwatch logo seochat tools logo