1

After getting moderately comfortable with Java, i'm now trying to expand my horizon and try my hand at C programming. However, I cannot seem to wrap my head around the pointers in C, even with having visited multiple videos and websites.

The code below is supposed to take in two strings from the user, get the length of both of them and then compare the lengths against one another. The program should then return the longest of the two names (taking great care to return the length until newline, not the allocated size for the variable) by means of a pointer. So, when the user inputs 'Peterson'(name1) and 'Thisisareallylonglastname'(name2) the program should return 'Thisisareallylonglastname' by means of the pointer / name2 connection.

The problem I am having is that when trying to run the code (written in the Eclipse Neon C/C++ IDE, using the MinGW compiler) I get no output in the console. I am fairly certain I have set the path to my MinGW install correctly in windows, but to be sure I have also added the enviroment manually to the project. Between my confusion for pointers and generally being a crappy coder I am not sure what the (undoubtedly novice) mistake with my program is. I am not getting errors of any kind in the Neon IDE.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{

    /* Two variables that take family names' input from the user with a maximum length of 256 */
    char name1[256];
    char name2[256];
    char *ch = NULL;

    printf("When two people marry there can sometimes be a debate which last/family name will henceforth be used (as a hyphenated last name is not always feasible.");
    printf("A simple way to avoid squabbles is to simply take the longest family name of the two (soon-to-be) partners.");
    printf("This program will take your name inputs and compare their length against one another; it will then return the longest name to be put on the document.");

    printf("Enter your last name for 1 :");
    gets(name1);
    printf("Enter your last name for 2 :");
    gets(name2);

    int size1 = strlen(name1);
    printf("Length of name 1:");
    printf(size1);

    int size2 = strlen(name2);
    printf("Length of name 2:");
    printf(size2);

    if (size1 > size2)
    {
        ch = &name1;
    }
    else
    {
        ch = &name2;
    }

    if(!ch)
    {
        printf("The largest family name found is:");
        printf(*ch);
    }

    return(0);

}
Nanne118
  • 125
  • 1
  • 13
  • You need to learn how [`printf`](http://en.cppreference.com/w/c/io/fprintf) works, because `printf(size1)` is *not* correct. – Some programmer dude Jan 17 '17 at 17:01
  • Always use the correct format specifiers i.e. `printf(size1);` -> `printf("%d", size1);` & `printf(size2);` -> `printf("%d", size2);` & I guess printf(*ch); should be `printf("%s", ch);` – George Jan 17 '17 at 17:02
  • Before using `gets()`, please read **["Why is the gets function so dangerous that it should not be used?"](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used)**. – J. Piquard Jan 17 '17 at 17:06
  • After playing with **Java**, it would be more 'natural' to try **C++** instead of **C** (same OOP for input/output...). – J. Piquard Jan 17 '17 at 17:08
  • @J.Piquard: That's nonsense! The "more natural" choise is what OP needs, not what the paradigm is. (and why learn two quite similar languages out of interest at all? Better learn different approaches) – too honest for this site Jan 17 '17 at 17:10
  • 1
    **Never ever** use `gets`. It is not part of the C standard (anymore). Use `fgets` instead. – too honest for this site Jan 17 '17 at 17:11

4 Answers4

0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{

    /* Two variables that take family names' input from the user with a maximum length of 256 */
    char name1[256];
    char name2[256];
    char *ch = NULL;

    printf("When two people marry there can sometimes be a debate which last/family name will henceforth be used (as a hyphenated last name is not always feasible.");
    printf("A simple way to avoid squabbles is to simply take the longest family name of the two (soon-to-be) partners.");
    printf("This program will take your name inputs and compare their length against one another; it will then return the longest name to be put on the document.");

    printf("Enter your last name for 1 :");
    gets(name1);
    printf("Enter your last name for 2 :");
    gets(name2);

    int size1 = strlen(name1);
    printf("Length of name 1: %d", size1);


    int size2 = strlen(name2);
    printf("Length of name 2: %d", size2);

    if (size1 > size2)
    {
        ch = name1;
    }
    else
    {
        ch = name2;
    }


    printf("The largest family name found is: %s", ch);



    return(0);

}

This should do the trick. You should also use scanf("%s", str) instead of gets.

When you do char name1[256] name1 is "considered an pointer", so you must do ch = name1 not ch = &name1, because both ch and name1 are pointers.

when you did:

if(!ch)
{
  printf...
}

you will only print if the ch is null, wich you don't want, because, in this case, you want to print if ch has a value so you should do:

if(ch)
{
  printf...
}

also in c printf must receive the information about the variable you are trying to print, check printf examples to understand it

0

One major problem is that your final output is under the condition if (!ch) - which, in English, reads "if the pointer ch is null-valued". Since it points to one of two (non-null) memory locations, this check will never pass.

If you change that to if (ch) (or just omit the check, since we know it's not null) and fix the printf problems pointed out by others in the comments, I think you'll get better results.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
0

A pointer to char and an array of char are both ways of representing strings in C and as such are the same type. The main difference being that with the array the memory is allocated at compile time and with a pointer you either assign an array to it (like you're trying to do) or dynamically allocate the memory.

So when you're doing

ch = &name1;

What you're actually doing is trying to assign a pointer to the string name1 to ch, which isn't the same type and should throw up an error. Instead you really want to be doing

ch = name1;

Conversely, *ch is the same as ch[0] - you're accessing the first character of the string so to print it out you want to have

printf("%s",ch);
Chris Turner
  • 8,082
  • 1
  • 14
  • 18
0

The main problem is that you're expecting printf to act as a polymorphic function like System.out.println, and it doesn't. The prototype for printf is

int printf( const char * restrict format, ... );

The first argument is always a character string; the string may contain conversion specifiers that control how any additional arguments are formatted.

So instead of writing:

printf("Length of name 1:");
printf(size1);

you'd write:

printf( "Length of name 1: %d\n", size1 );

or

printf( "Length of name 1: " );
printf( "%d\n", size1 );

The %d in the format string tells printf that the corresponding argument should have type int, and that you want to display its value as a string of decimal digits. See the online C 2011 standard, section 7.21.6.1, for the complete list of conversion specifiers.

printf doesn't automatically append a newline to all output the way System.out.println does - you have to specify it in the format string (\n).

Standard output is typically line buffered - output won't show up on the console until a) the buffer is full, b) the buffer is manually flushed with fflush, c) a newline appears in the buffer, or d) an input function (fgets, scanf, etc.) immediately follows the output function.

Array semantics in C and Java are wildly different. In C, arrays are not reference objects - they don't point to dynamically-allocated memory on the heap. However, the array subscript operation a[i] is defined in terms of pointer arithmetic - *(a + i). What happens in C is that when an array expression is not the operand of the sizeof or unary & operators, or isn't a string literal used to initialize an array in a declaration, the expression is converted ("decays") from type "N-element array of T" to "pointer to T", and the value of the expression is the address of the first element of the array.

This is a very long-winded way of saying that instead of writing

 ch = &name1;

you should be writing

 ch = name1;

instead. The expression name1 "decays" to a pointer to the first element of the array, and the resulting type of the expression is char *. The type of the expression &name1 is char (*)[256] (pointer to 256-element array of char), which is not what you want. They'll both evaluate to the same location (modulo any type conversions), but type matters.

Finally...

NEVER NEVER NEVER NEVER NEVER use gets. It will introduce a point of failure / major security hole in your code. It was deprecrated shortly after the release of the C99 standard, and has been officially removed from the standard library in C2011. That one library function has been responsible for untold amounts of mayhem over the decades. Do not use it, not even in toy code. It is the "Highlander II" of the C programming language - it never existed. Use fgets instead.

John Bode
  • 119,563
  • 19
  • 122
  • 198