How to print elements by use of Pointers - c

Greetings,
I had been studying C++ for a while now.
I'm getting in to pointers now.
But I'm creating a program on C++ that will ask for a string("%s") input.
And I want to display its character on a different line.
But when I run the program I get the wrong letters.
Here's my code;
#include<stdio.h>
#include<stdlib.h>
main() {
char* name;
name = (char *)malloc(sizeof(char));
printf("Enter string: "); scanf("%s", name);
while(*name != '\0') {
printf("%c", name); *name++
}
}
Your reply is highly appreciated.

malloc(sizeof(char)) allocates space for a single character. This is probably not what you want. As the comments below point out, the dereferencing in *name++ is pointless. It does no harm, but perhaps indicates that you're thinking incorrectly about something. name++ has the same effect.

First, if you are going to study C++, you should learn to write C++ programs, not C programs. Here is your program in idiomatic C++:
#include <iostream>
#include <string>
int main(int, char **) {
std::string name;
std::cout << "Enter string: " << std::flush;
std::cin >> name;
std::cout << name << "\n";
}
One advantage of using C++ and its standard libraries over C and its standard libraries is precisely this: you almost never need to use pointers.
But, taking your program for what it is worth, there are sevearal problems. First, in C++, if you want to access the C header files, you should include them with their C++ names:
#include <cstdio>
#include <cstdlib>
Next, main requires a proper signature:
int main(int, char**) {
Most crucially, you are not allocating enough space for your user's name:
name = (char *)malloc(A_BIG_ENOUGH_NUMBER);
Here, you must allocate enough space that scanf() will not write beyond the end of your buffer. But, you can't possibly know how big that is until afte scanf runs. This catch-22 is the source of "buffer-overflow" bugs. For your test program, since you control the input, it is probably OK to just pick a number bigger than any name you'll ever type. In production code, you must NEVER, EVER, used scanf in this way.
name = (char *)mallocc(40);
By the way, if you are compiling this as C code, you should never cast the return from malloc. If you are compiling this as C++ code, you must always cast the return from malloc.
printf("%c", *name); name++
This line is missing a semicolon. Did you compile this program? In future, please only post code that you have compiled. Please use your computer's cut-and-paste features to post your code, never retype the code by hand.
This line has two other problems. First, you must derefence the name pointer to access the data to which it points. (So, *name instead of name.) Second, you need not dereference name in the second statement on this line, since you do nothing with the resulting pointed-to data. (So, name++ instead of *name++.)
Finally, and most importantly, buy, read, and learn from a good book.

Your program is likely printing junk because you only allocate one byte to your string buffer. When the user enters a string, you will have undefined behavior because the scanf will write past the end of name.
You need to alloc name like this:
char *name = (char *)malloc(MAX_STRING_SIZE, sizeof(char));
Even better to use calloc instead of malloc. Define MAX_STRING_SIZE however you like. A reasonable size depends on the application. In your case, if the users will be entering short strings, then perhaps a reasonable buffer size is 64 bytes, or perhaps 80 or 100.
Also, in your while loop, you can increment and dereference your pointer in one step, like this:
printf("%c", *name++);
If you don't like to be that terse, then you can break them apart, but you don't need to dereference the pointer to increment it.
printf("%c", *name); name++;

That's not C++, it's C.
malloc(sizeof(char)) will allocate storage of one char, I expect you wanted more than that.
Also there is no need to allocate dynamically here. Try:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char name[256];
char *p = name;
printf("Enter string: ");
scanf("%s", name);
while (*p != '\0') {
printf("%c", *p);
p++;
}
return 0;
}

Related

C reading from a CSV file zeroes displayed after each record [duplicate]

I have written the following piece of code:
int main() {
char arrays[12];
char *pointers;
scanf("%s", arrays);
scanf("%s", pointers);
printf("%s", arrays);
printf("%s", pointers);
return 0;
}
Why does it give an error when I write scanf("%s", pointers)?
char *pointers;
must be initialized. You can not scan string into pointers until you point it to some address. The computer needs to know where to store the value it reads from the keyboard.
int main() {
char arrays[12];
char *pointers = arrays;
scanf("%s", pointers);
printf("%s", pointers);
return 0;
}
Because you're writing to an address in memory that has not been initialized. Writing to memory pointer by an uninitialized pointer invokes undefined behaviour. Either allocate enough memory:
pointers = malloc(256);
if(!pointers)
perror("malloc");
else
scanf("%255s", pointers);
Or declare it as a static array:
char pointers[256];
You should also consider using fgets() instead of scanf().
You may want to read i you are interested in fgets():
Difference between scanf() and fgets()
char *pointers; creates a pointer variable.
pointers is the address pointed to by pointers, which is indeterminate by
default.
*pointers is the data in the address pointed to by pointers, which you cannot do until address is assigned.
Just do this.
char arrays[12];
char *pointers;
pointers = arrays;
scanf("%s",pointers);
pointers is being used without initialisation, like int x; printf("%d\n", x);. You need to make your pointer point to something before using it. Which book are you reading?
pointers is an unitialized pointer. You are not able to write into it. You shall allocate enough memory to store a string, as you did with arrays. With a pointer, it is possible to use dynamic allocation (cf. malloc).
Could you elaborate on the error, i'm not around a compiler right now.
But for scanf and printf to work you must have this at the top of your program:
#include <stdio.h>
#include <stdlib.h>
Both are standard libraries for C. IO contains scanf, I'm fairly sure printf is in the same. But until you know which libraries you need for which functions it doesn't hurt to include both standard libraries for every program. Try to use custom header files as well so you don't need mass #includes for every file.
Don't forget malloc statements for memory allocation.
But I'm unsure what you're attempting to do with your code, please elaborate?

gets and puts to get and print a string

i'm trying to get and print a string with gets and puts but i get a segmentation fault error when i use them togheter.
this is the code i'm trying to get this working. [i type the string "prova" to test it]
int main()
{
char *s;
gets(s);
puts(s);
return 0;
}
if i change "gets" with "scanf" i get the same error.
if i change "puts" with "printf("%s", s)" i get the output.
if i declare char *s = "prova" and then puts(s) i get the output.
i also tried to change char *s; with char s[] but i get the same error.
where i'm i wrong on this? ty very much
i know gets is bad, is just bc i'm writing exercise from "C how to program, fifth edition" by Deitel and Deitel
You have multiple problems with that piece of code. To start with gets have been deprecated since the C99 standard, and in the C11 standard it has been removed. The reason is that it's not very safe, and has no bounds-checking and so can write beyond the bounds of the memory you pass to it leading to buffer overflows.
Secondly, you use the uninitialized local variable s. The value of an uninitialized variable is indeterminate, and will be seemingly random. Using an uninitialized local variable leads to undefined behavior, which often leads to crashes.
Another problem is if you initialize s to point to a literal strings. Literals strings are constant (read-only) arrays of characters, and attempting to write to it will again lead to undefined behavior.
You need to allocate some room for the string:
char s[256];
gets(s);
puts(s);
But gets is bad. (It doesn't know how big your buffer is, so what happens if more than 255 characters are read?)
The most important mistake you have is that you are declaring a char pointer, but you are not reserving the space in memory where the characters will be stored, so you got a pointer that point to some random memory adress that you should'nt use. the "right" thing to do will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT); //here you make the pointer point to a memory adress that you can use
gets(s);
puts(s);
free (s);
return 0;
}
But also is strongly recommend to avoid using gets because that function doesn't check for the length of the input, so use fgets instead that allow you to do that, you will only need to set the data stream to stdin.
The code will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT);
fgets(s,20,stdin);
puts(s);
free(s);
return 0;
}

How can I use gets() in a function to assign string in char *ch?

How can I write gets(???);
Thank you.
void getStr(**temp){
gets(???);
}
void main(){
char *ch;
printf("Enter a string: \n");
getStr(&ch);
printf("main: %s\n", ch);
}
------ Output ------
Enter a string:
abc
main: abc
Never use the gets function. It is inherently unsafe, since there's no way to guard against overruns (the user entering more data than you're prepared to accept). In fact, it was removed from the language by the 2011 ISO C standard.
You should probably use fgets() instead. It's a bit more complicated to use (for one thing, it leaves the '\n' line terminator in the string), but it lets you specify the maximum number of characters to be read.
Your getStr function probably doesn't need to take a char** argument; a char* would do, since it's not going to be modifying the pointer, just reading data into an array to which the pointer points.
You'll need to allocate a char array to read the data into. You can either declare an array object:
char line[200]; // for example
or use malloc to allocate the space.
One more thing: void main() is incorrect. (Compilers are allowed to accept it, but there is no good reason to use it.) The correct definition is int main(void). If you have a book that's telling you to use void main(), it was written by someone who doesn't know the C language very well, and it's likely to have more serious errors.
Take a look at the comp.lang.c FAQ.

using scanf function with pointers to character

I have written the following piece of code:
int main() {
char arrays[12];
char *pointers;
scanf("%s", arrays);
scanf("%s", pointers);
printf("%s", arrays);
printf("%s", pointers);
return 0;
}
Why does it give an error when I write scanf("%s", pointers)?
char *pointers;
must be initialized. You can not scan string into pointers until you point it to some address. The computer needs to know where to store the value it reads from the keyboard.
int main() {
char arrays[12];
char *pointers = arrays;
scanf("%s", pointers);
printf("%s", pointers);
return 0;
}
Because you're writing to an address in memory that has not been initialized. Writing to memory pointer by an uninitialized pointer invokes undefined behaviour. Either allocate enough memory:
pointers = malloc(256);
if(!pointers)
perror("malloc");
else
scanf("%255s", pointers);
Or declare it as a static array:
char pointers[256];
You should also consider using fgets() instead of scanf().
You may want to read i you are interested in fgets():
Difference between scanf() and fgets()
char *pointers; creates a pointer variable.
pointers is the address pointed to by pointers, which is indeterminate by
default.
*pointers is the data in the address pointed to by pointers, which you cannot do until address is assigned.
Just do this.
char arrays[12];
char *pointers;
pointers = arrays;
scanf("%s",pointers);
pointers is being used without initialisation, like int x; printf("%d\n", x);. You need to make your pointer point to something before using it. Which book are you reading?
pointers is an unitialized pointer. You are not able to write into it. You shall allocate enough memory to store a string, as you did with arrays. With a pointer, it is possible to use dynamic allocation (cf. malloc).
Could you elaborate on the error, i'm not around a compiler right now.
But for scanf and printf to work you must have this at the top of your program:
#include <stdio.h>
#include <stdlib.h>
Both are standard libraries for C. IO contains scanf, I'm fairly sure printf is in the same. But until you know which libraries you need for which functions it doesn't hurt to include both standard libraries for every program. Try to use custom header files as well so you don't need mass #includes for every file.
Don't forget malloc statements for memory allocation.
But I'm unsure what you're attempting to do with your code, please elaborate?

How do I transfer text between different functions in C?

I have two .c files that I would like to compile into on executable. Having just started learning C, I'm finding it tricky to know how to transfer text as an argument between functions (which I've found to be incredibly simple in every other language).
Here are the two files:
Program.c
#include <stdio.h>
#include <string.h>
int main(){
char temp[40] = stringCall();
printf("%s",temp);
}
StringReturn.c
#include <stdio.h>
#include <string.h>
char[] stringCall(){
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
}
I usually get a problem that says something like "Segmentation Failed (core dumped)" or alike. I've done a lot of Googling and amazing I can't really find a solution, and certainly no simple tutorial "This is how to move text between functions".
Any help would be appreciated :)
char toReturn[40] = "Hello, Stack Overflow!";
return toReturn;
This is invalid, you're returning an auto array which gets out of scope after the function returns - this invokes undefined behavior. Try returning the string literal itself (it's valid throughout the program):
return "Hello, Stack Overflow!";
Or a dynamic duplicate of your array:
char toReturn[40] = "Hello, Stack Overflow!";
return strdup(toReturn);
In this latter case, you'll need to free() the string in the caller function.
You are correct, this isn't simple in C because C can't treat strings as values.
The most flexible way to do it is this:
// Program.c
char temp[40];
if (stringCall(temp, sizeof temp) <= sizeof temp) {
puts(temp);
} else {
// error-handling
puts("My buffer wasn't big enough");
}
// StringReturn.c
int stringCall(char *buf, int size) {
const char toReturn[] = "Hello, Stack Overflow!";
if (sizeof toReturn <= size) {
strcpy(buf, toReturn);
}
return sizeof toReturn;
}
stringCall doesn't return the string data, it writes it to a buffer supplied by the caller
A buffer always comes with a size. You could use size_t or ssize_t for this rather than int.
stringCall checks the size before writing. There are other ways to do this in a single call, all of which are either not in C89 and C99, or are defective in some other way. C11 introduces strcpy_s. Use what tools you can, which should be logically equivalent to checking it yourself as in my code above. Never forget to make sure there's space for the nul terminator, which invisibly lurks at the end of every C string.
stringCall returns the number of bytes that it wants to write, even if it doesn't write anything. This means that a caller whose buffer is too small can allocate a bigger one and try again. For that matter a caller can do stringCall(NULL, 0) to get the size without trying any particular buffer.
I'm using sizeof here because I'm using arrays whose size is known by the compiler, but in practice stringCall might use strlen or some other way of knowing how much data it wants to write.
As I've written it, callers are required not to pass in a negative value for size. That's usually OK, because their buffer in point of fact cannot have a negative size, so their code is already buggy if they do. But if you want to be really sure, or if you want to help your callers catch those bugs, you could write if ((int) sizeof toReturn < size) or if (size > 0 && sizeof toReturn < size).
"Most flexible" isn't always best, but this is good when the function is actually generating the text on the fly, especially when there isn't an easy way for the caller to know the length in advance without doing half the work that stringCall is supposed to do for them. The interface is similar to the C99 standard function snprintf.

Resources