Characters and strings in ANSI C

  • Thread starter Thread starter AK2
  • Start date Start date
  • Tags Tags
    Strings
Join the discussion
Registration is free. Ask a follow-up in this thread, or start your own.
7 replies · 6K views
AK2
Messages
39
Reaction score
0
I am doing a question (its not home work just an exercise). The following is the question.
Code:
 Write code that allocates space for an 80-character string and then inputs a string from the keyboard and stores it in the allocated space.

This is my code.
Code:
#include <stdio.h>
#include <stdlib.h>
char *ptr, *p;
main()
     {
       ptr = malloc(81);
       p = ptr;
       printf("Enter some text");
       gets("p");
       printf("You entered : %s", *ptr);
       return 0;
     }
I run it using Dev C++ development ide which uses the GNU C compiler.
The code compiled. It didnt run and it gave an error message. This is frustrating. If possible can someone explain gets() function and malloc function because I'm not really understanding it from the book I'm using. I understand the basics like what strings are, characters, ASCII code and the like.
 
Physics news on Phys.org
D H said:
The problem is the line gets("p"). You are telling the computer to read user input into "p", a const char[2] string rather than the character array p.

Get rid of the quotes around p.


I did what you told me about removing the double quotations around p. The code compiles but it does not run.
 
Two problems remain:
  1. printf("Enter some text");
  2. printf("You entered : %s", *ptr);

The second item will cause your program to blow up. I'll leave correcting that line as an exercise to the original poster.

The problem with the first item is a bit more subtle. At this early stage of your programming education, I suggest you add a newline to the end of this prompt: Change this to

printf("Enter some text\n");

The problem here is that printf buffers its output. The default, at least in Unix systems, is to line-buffer the output. Printing one character at a time is very expensive in terms of CPU time. Printing a bunch of characters is still expensive, but not much more expensive than printing one character. In line buffering mode, the system stores output until it gets a newline to print, at which point it prints the entire buffered line.

Suppose you fix the second highlighted line but not the first. The program will run. However, if your system is using line-buffering as the default, the prompt to enter text won't appear until after you enter the text.

There are ways to control the buffering. fflush(FILE *stream) will force whatever output is buffered for the specified output stream to be sent to the output device. setvbuf (FILE *stream, ...) let's you set the buffering for the specified output stream to fully buffered, line buffered, or unbuffered.
 
jtbell said:
What exactly do you mean by "does not run?"

I'm sorry for not explaining myself well. It runs but when I enter a line and press enter, there is an error message and the object code doesn't print the line I entered out.

D H said:
Two problems remain:
  1. printf("Enter some text");
  2. printf("You entered : %s", *ptr);

The second item will cause your program to blow up. I'll leave correcting that line as an exercise to the original poster.

The problem with the first item is a bit more subtle. At this early stage of your programming education, I suggest you add a newline to the end of this prompt: Change this to

printf("Enter some text\n");

The problem here is that printf buffers its output. The default, at least in Unix systems, is to line-buffer the output. Printing one character at a time is very expensive in terms of CPU time. Printing a bunch of characters is still expensive, but not much more expensive than printing one character. In line buffering mode, the system stores output until it gets a newline to print, at which point it prints the entire buffered line.

Suppose you fix the second highlighted line but not the first. The program will run. However, if your system is using line-buffering as the default, the prompt to enter text won't appear until after you enter the text.

There are ways to control the buffering. fflush(FILE *stream) will force whatever output is buffered for the specified output stream to be sent to the output device. setvbuf (FILE *stream, ...) let's you set the buffering for the specified output stream to fully buffered, line buffered, or unbuffered.

Thanks a lot for your help. Below is my improved code and it works very well.
Code:
#include <stdio.h>
#include <stdlib.h>
char *ptr, *p;
main()
     {
     ptr = malloc(81 * sizeof(char));
     if (ptr == NULL)
       {
         puts("Memory wasn't allocated");
         exit (1);
       }    
     printf("Enter a line");
     gets(ptr);
     [b]printf("You entered %s\n", ptr);[/b]
     getchar();
     return 0;
     }
\
edit: Even though I removed the * operator from I don't really understand why it is so. I know that *ptr refers to the contents of a variable while ptr refers to the address. can u clear it up for me because I'm confused.
 
Last edited:
AK2 said:
edit: Even though I removed the * operator from I don't really understand why it is so. I know that *ptr refers to the contents of a variable while ptr refers to the address. can u clear it up for me because I'm confused.

"ptr" refers to the contents of a variable named "ptr".

"&ptr" refers to the address of a variable named "ptr".

"*ptr" does something slightly different. *ptr assumes that the contents of ptr are a memory address, and returns the value at the memory address stored in the variable "ptr". You can only say "*ptr" if ptr actually is typed as a pointer.

I'm not sure if that was clear, but here's the trick:

When you pass a variable to printf with %s, it is looking for a "string". But a string in C is just an array of characters. It is inconvenient to pass a whole array as an argument, so instead you use a trick. You pass a pointer to the first character in the array. Printf then just looks at every character in the array until it finds a '\0' character (which printf assumes means the end of the character array).

"ptr" is a variable containing a memory address, which points to the first character in the array created by your "malloc" call. So if you pass "ptr" to printf, it gets the memory location of the first character in the array and it is happy. But if you pass "*ptr" to printf, that is not what printf wanted. "*ptr" is the specific character pointed to by the value in "ptr"-- "*ptr" is the first character in the string. So if you pass *ptr to printf, it will just get some garbage that looks like whatever the first letter in the string is. But, printf will think that garbage is a pointer, and it will treat it like a pointer, and it will go to whatever memory address the garbage corresponds to and crash.
 
Coin said:
"ptr" refers to the contents of a variable named "ptr".

"&ptr" refers to the address of a variable named "ptr".

"*ptr" does something slightly different. *ptr assumes that the contents of ptr are a memory address, and returns the value at the memory address stored in the variable "ptr". You can only say "*ptr" if ptr actually is typed as a pointer.

I'm not sure if that was clear, but here's the trick:

When you pass a variable to printf with %s, it is looking for a "string". But a string in C is just an array of characters. It is inconvenient to pass a whole array as an argument, so instead you use a trick. You pass a pointer to the first character in the array. Printf then just looks at every character in the array until it finds a '\0' character (which printf assumes means the end of the character array).

"ptr" is a variable containing a memory address, which points to the first character in the array created by your "malloc" call. So if you pass "ptr" to printf, it gets the memory location of the first character in the array and it is happy. But if you pass "*ptr" to printf, that is not what printf wanted. "*ptr" is the specific character pointed to by the value in "ptr"-- "*ptr" is the first character in the string. So if you pass *ptr to printf, it will just get some garbage that looks like whatever the first letter in the string is. But, printf will think that garbage is a pointer, and it will treat it like a pointer, and it will go to whatever memory address the garbage corresponds to and crash.

While reading the unblolded piortion on the post I didnt get it. When I read the bolded part I understood the whole post. Thanks for the clearing it up for me. Sometimes I forget some pointers are variables.