gets and puts to get and print a string - c

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;
}

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?

C - scanf() and then getenv()

I'm asking the user which environment variable he want to know and then I scan it with scanf. But it doesnt work for me. Here is my code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char *value;
char input;
printf("Which variable do you want?\n");
scanf("%s", input);
value = getenv(input);
printf("%s", value);
}
The compiler says:
"Function argument assignment between types "const char*" and "char" ist not allowed"
So i tried to change the input variable to: char const *input
Now there is no compiler error, but when I submit a name, for example "USER", I get a "Segmentation fault (core dumped)" error.
The warning is because here
value = getenv(input);
you pass a char to getenv(), which has the prototype:
char *getenv(const char *name);
Define input as a char array like:
char input[256];
printf("Which variable do you want?\n");
scanf("%255s", input); //specify the width to avoid buffer overflow
Or, you can use dynamically memory allocation (using malloc) if you think 256 is not big enough for your purposes.
When you defined char *input; you satisfy the compiler because your syntax is valid: when calling scanf("%s", input); you are saying you want a string and it should get placed wherever input is.
The problem is input isn't anywhere (initialized) yet... where it points is undefined at the moment; before using any pointer you must make it point somewhere that is valid (and large enough to hold whatever you intend to put there).
There are a few ways you can solve this, but perhaps the easiest is to decide how large the input needs to be and declare a character array, such as: char input[512];. Be aware that this is problematic because if the input exceeds your buffer you will overwrite other memory... but this should get you moving forward for now.
char is a single char.
char *input declares a variable which hold a pointer to a character, but there is no memory for the data. In C, this is a correct behavior. However, sscanf expects that you actually pass a pointer which points to allocated memory (please consider that the function does not return any pointer, so it has no chance of allocating memory for you).
So between declaration and use, please use malloc to allocate memory.

String size is equal to number of characters

I was making a basic program of strings and did this. There is a string in this way:
#include<stdio.h>
int main()
{
char str[7]="network";
printf("%s",str);
return 0;
}
It prints network.In my view, it should not print network. Some garbage value should be printed because '\0' does not end this character array. So how it got printed? There were no warning or errors too.
That's because
char str[7]="network";
is the same as
char str[7]={'n','e','t','w','o','r','k'};
str is a valid char array, but not a string, because it's no null-terminated. So it's undefined behavior to use %s to print it.
Reference: C FAQ: Is char a[3] = "abc"; legal? What does it mean?
char str[7]="network";
This Invokes Undefined behavior.
You did not declared array with enough space
This should be
char str[8]="network";
char str[7]="network";
you did not provide enough space for the string
char str[8]="network";
It's possible that stack pages start off completely zeroed in your system, so the string is actually null-terminated in memory, but not thanks to your code.
Try looking at the program in memory using a debugger, reading your platform documentation or printing out the contents of str[7] to get some clues. Doing so invokes undefined behavior but it's irrelevant when you're trying to figure out what your specific compiler and OS are doing at one given point in time.

Creating one array of strings in C fails, why?

I tried to create one array of strings in C. Here is the code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main()
{
char *foo[100];
strcpy(foo[0], "Testing this");
printf("%s ", foo[0]);
return 1;
}
But when I compile it, it simply breaks. No error, no nothing, it simply doesn't work and breaks. Any suggestion? When I tri char *foo[10] it works, but I can't work with just 10 strings
You allocated an array of pointers but did not allocate any memory for them to point to. You need to call malloc to allocate memory from the heap.
char *foo[100];
foo[0] = malloc(13);
strcpy(foo[0], "Testing this");
Naturally you would need to free the memory at some later date when you were finished with it.
Your code invokes what is known as undefined behavior. Basically anything can happen, including the code working as you intended. If the version with char *foo[10] works as you intended that's simply down to luck.
As an aside, your main() definition is wrong. It should be int main(void).
You're assigning an unallocated pointer. char *foo[100] is an array of 100 unallocated pointers, and they point to unknown locations in memory, ones which you can probably not access.
You are creating an 100 pointers to point no where. As explained by David, you need to dynamically allocate the memory. However, you can also have the compiler do this for you if you know the size of the strings (or max):
// Create an array of 10 strings of size 100 and initialize them automatically
char foo[10][100] = {0};
// Now you can use it them and not worry about memory leaks
strcpy(foo[0], "text");
// Or use the safer version
strcpy_s(foo[0], 100, "text");
Expanding upon other people's answers:
char *foo;
is a pointer to a character. It may be assigned the address of a single character or assigned the address of the first of a sequence of characters terminated by '\0'. It may also be assigned an address via malloc().
char foo[100];
is space for 100 characters or space for a string of up to 99 characters and a terminating '\0' character.
char *foo[100];
is 100 character pointers, i.e., 100 char *foo; types.
#include <stdlib.h>
#include <stdio.h>
int main(void){
char *foo[100];
foo[0] = malloc(13*(sizeof(char)));
strcpy(foo[0], "Testing this");
printf("%s ", foo[0]);
return 0;
}
This is the corrected version of your code.
MISTAKE: not allocating enough memory for the string.
CORRECTION: using malloc to allocate 13 blocks of memory for the string.

How to print elements by use of Pointers

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;
}

Resources