Characters and strings in ANSI C

  • Thread starter Thread starter AK2
  • Start date Start date
  • Tags Tags
    Strings
Click For Summary

Discussion Overview

The discussion revolves around a coding exercise in ANSI C that involves memory allocation for a string and user input handling. Participants explore the use of the `malloc` function for dynamic memory allocation and the `gets` function for reading input, while addressing issues related to string handling and output buffering.

Discussion Character

  • Homework-related
  • Technical explanation
  • Conceptual clarification
  • Debate/contested

Main Points Raised

  • One participant shares their code and expresses frustration over errors encountered when running it, specifically regarding the `gets` function and `malloc` usage.
  • Another participant points out that the use of quotes around the variable `p` in `gets("p")` is incorrect, suggesting to remove the quotes to properly read input into the allocated memory.
  • After making changes, the original poster reports that the code compiles but still does not run correctly, prompting further clarification on what "does not run" means.
  • A participant explains that the output from `printf` may not appear immediately due to output buffering, suggesting the addition of a newline character to the prompt for better visibility.
  • Concerns are raised about the use of `printf("You entered : %s", *ptr);`, with a participant indicating that this line will cause issues and leaving the correction as an exercise for the original poster.
  • The original poster later shares an improved version of their code, which they claim works well, but expresses confusion about the use of the `*` operator with pointers.
  • Another participant clarifies the difference between `ptr`, `&ptr`, and `*ptr`, explaining how they relate to memory addresses and string handling in C.

Areas of Agreement / Disagreement

Participants generally agree on the issues related to the original code and the corrections needed. However, there remains some uncertainty regarding the understanding of pointers and how they interact with functions like `printf`.

Contextual Notes

The discussion highlights limitations in understanding the behavior of `gets` and `malloc`, as well as the nuances of output buffering in C programming. There are also unresolved questions about pointer usage and string representation in function calls.

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
10K
  • · Replies 5 ·
Replies
5
Views
3K
Replies
16
Views
6K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 18 ·
Replies
18
Views
4K
Replies
5
Views
2K
Replies
14
Views
4K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 6 ·
Replies
6
Views
3K