Characters and strings in ANSI C

  • Thread starter Thread starter AK2
  • Start date Start date
  • Tags Tags
    Strings
Click For Summary
The discussion focuses on a coding exercise in ANSI C involving string allocation and input. The original code attempted to use the `gets()` function incorrectly, leading to runtime errors due to improper handling of pointers. Key corrections included removing quotes around the pointer variable and ensuring proper output buffering with `printf()`. The final code successfully allocates memory for an 80-character string, reads user input, and prints it correctly. Clarifications on pointer usage emphasized the difference between a pointer's address and the value it points to, which is crucial for understanding string manipulation in C.
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.
 
Technology news on Phys.org
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.
 
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.
 
What exactly do you mean by "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.
 

Similar threads

Replies
7
Views
2K
  • · Replies 118 ·
4
Replies
118
Views
9K
  • · Replies 5 ·
Replies
5
Views
2K
Replies
16
Views
6K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 18 ·
Replies
18
Views
4K
Replies
5
Views
2K
Replies
14
Views
3K
  • · Replies 4 ·
Replies
4
Views
1K
  • · Replies 6 ·
Replies
6
Views
3K