Accept string using scanf and display them using printf [duplicate] - c

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
I cannot retrieve string using printf . instead getting error : segmentation fault
int main(){
char * a[5];
int i;
printf("\n enter value ");
for (i=0;i<5;i++){
printf("%d Name :\n",i);
scanf("%s",&a[i]);
}
printf("%s",a[2]);
printf("%s",a[3]);
}
~

char * a[5]; is array of 5 char pointer that means you can store 5 char buffer of any length.
The problem is in the statement
scanf("%s",&a[i]); replace this with scanf("%s",a[i]);
case 1 :-
int main(){
char *a[5] = {"stackoverflow","meta","ask ubuntu","super","unix"};
/* here a[row] can have any number of char */
for (int i = 0 ;i < 5;i++) {
printf("%s\n",a[i]);
}
return 0;
}
Case 2 :-
int main(){
char *a[5];
for (int i=0;i<5;i++){
printf("%d Name :\n",i);
a[i] = malloc(MAX);/* define MAX how many char you want to store into that */
scanf("%s",a[i]); /* & not required as a[i] itself address */
}
for (int i = 0 ;i < 5;i++) {
printf("%s\n",a[i]);
}
/* don't forget to free once job is done */
for (int i = 0 ;i < 5;i++) {
free(a[i]);
}
return 0;
}

You shouldn't input to a char* .
And you shouldn't store any string by char*, including string literal, in fact, string literal convert to char* is deprecated many years ago.
Use char a[5][MaximumLength] instead. MaximumLength should be a literal.

The problem is you are using a pointer before it has been initialized. It does not yet point at valid memory. These leads to program crashes or other kinds of unexpected behavior, such as "segmentation faults".
So you should edit it to:
char* my_string = malloc(size+1);
The %c format specifier is used whenever we want to be specific that the variable that we are going to printf or scanf is of type char.
On the other hand the %s format specifier is used to specify to the printf or scanf functions that contents of the address that is specified as the next parameter are to considered as string.
You are taking char as input, not the whole string.
scanf("%s",&a[i]);, will be scanf("%c",&a[i]);
printf("%s",a[3]);, will be printf("%c",a[3]);
printf("%s",a[2]);, will be printf("%c",a[2]);
The following code worked fine:
#include<stdio.h>
#include<stdlib.h>
int main(){
char* a = malloc(size+1); // where size is max string length
int i;
printf("\n enter value ");
for (i=0;i<5;i++){
printf("%d Name :\n",i);
scanf("%c",&a[i]);
printf("%c\n",a[i]);
}
printf("%c\n",a[2]);
printf("%c\n",a[3]);
free(a);
}

Related

The number of inputs I have to enter is one more than required for the output to display [duplicate]

This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 11 months ago.
The community reviewed whether to reopen this question 11 months ago and left it closed:
Original close reason(s) were not resolved
I have to enter one more input than required for the code to start running. For example, for 2 strings I have to enter 3 strings, only then the output shows. Please help.
#include<stdio.h>
#include<string.h>
int main () {
int num_strings;
char arr[num_strings][100];
scanf("%d",&num_strings);
for (int i=0;i<=num_strings-1;i++) {
scanf("%s\n",&arr[i]);
}
for (int j=0;j<=num_strings-1;j++) {
if (strlen(arr[j])>10) {
printf("%c%d%c",arr[j][0],strlen(arr[j])-2,arr[j][strlen(arr[j])-1]);
printf("\n");
} else {
printf("%s",arr[j]);
printf("\n");
}
}
}
The following
int num_strings;
char arr[num_strings][100];
scanf("%d",&num_strings);
is out of order. Changing the value of num_strings does not retroactively adjust the size of arrays that were initialized using this variable. As such, arr is initialized with an indeterminate value, since num_strings is uninitialized. This is an example of invoking Undefined Behavior.
&arr[i] is of type char (*)[100], you simply want arr[i], which will decay to a char * (the correct type for %s) when passed to scanf.
Remove the trailing whitespace from the scanf format, or it will hang until it reads non-whitespace ("%s\n" -> "%s").
Limit the length of the strings you read with a field-width specifier as to not overflow the buffers (%99s).
strlen returns a size_t, the format specifier for printing this is %zu.
Note that scanf can fail for a variety of reasons. Consider checking that the return value of each call was (or was not) the expected number of conversions, e.g.,
if (2 != scanf("%d%d", &a, &b))
/* failure */;
and handle any failures.
Here is a functional version of your program, without error checking:
#include <stdio.h>
#include <string.h>
int main(void) {
int num_strings;
scanf("%d", &num_strings);
char arr[num_strings][100];
for (int i = 0; i < num_strings; i++)
scanf("%99s", arr[i]);
for (int j = 0; j < num_strings; j++) {
if (strlen(arr[j]) > 10) {
printf("%c%zu%c\n",
arr[j][0], strlen(arr[j]) - 2,
arr[j][strlen(arr[j]) - 1]);
} else {
printf("%s\n", arr[j]);
}
}
}
stdin:
3
hello
thisisalongerstring
world
stdout:
hello
t17g
world

Create an array of unknown strings - Undefined behaviour

In what way is the following code faulty or undefined behaviour?
I suggested this as a possibility to create an array of strings, if string number and size are unknown beforehand, and after a short discussion, it was suggested that I open a new question.
The following code produced the expected results when I compiled it with gcc, but that can happen in spite of undefined behaviour (it's undefined after all).
So, what is the mistake?
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
scanf("%s", &words[i]);
}
for (i = 0; i < n; ++i) {
printf("%s\n", &words[i]);
}
Edit:
I feel stupid now for missing this, I guess getting the correct answer back just made me miss my error. But that others may learn from my mistake:
I guess I got completely wrong what the & operator does. I thought it would give me where words points to, but of course it does the exact opposite. See the answers.
scanf("%s", &words[i]); and printf("%s\n", &words[i]); invokes *undefined behavior because data having wrong type are passed.
In both of scanf() and printf(), %s requires char* pointing at valid buffer but what is passed are char**.
Also don't forget to allocate buffer to store strings before reading.
Try this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n, i;
printf("How many strings? ");
scanf("%d", &n);
char *words[n];
for (i = 0; i < n; ++i) {
printf("Input %d. string: ", i + 1);
words[i] = malloc(1024001); /* allocate enough buffer */
if (words[i] == NULL) {
perror("malloc");
return 1;
}
scanf("%1024000s", words[i]); /* limit length to read to avoid buffer overrun */
}
for (i = 0; i < n; ++i) {
printf("%s\n", words[i]);
}
for (i = 0; i < n; ++i) {
free(words[i]); /* clean what is allocated */
}
return 0;
}
char *words[n];
creates an array of uninitialized pointers
scanf("%s", foo);
writes values to the position foo is pointing to
it is not specified where the pointers of words are pointing to so they could point anywhere which could result in a segfault
next words is a char**
words[i] is a char *
&words[i] is a char **
%s expects a char* so it's again undefined behavior what happens
so you first have to initialize your words arrays using for example malloc and then write the values to words[i]
This:
char *word;
is a pointer, Before it is used as a container for say a string, it needs to point to memory sufficient for the string.
for example, this will work
word = malloc(80*sizeof(*word));
if(word)
{//success, continue
Similar to above, this:
char *word[n];
extension is an an array of n pointers. Before any of the pointers can be used as a container for say some strings, each needs to point to its own memory location. Assuming the value n has been scanned in, this will work:
for(int i=0;i<n;i++)
{
word[i] = malloc(80*sizeof(*word[i]));//80 for illustration
if(!word[i])
{//handle error...
Once the memory is allocated, the strings can be populated.
However, to ensure user input does not overflow the buffer defined by each instance of word, use a width specifier in the format string:
Change:
scanf("%s", &words[i]);
To:
scanf("%79s", words[i]);//note & is not needed as the symbol for a char array serves as the address
// ^^ ^

Garbage characters are printed forcefully [duplicate]

This question already has answers here:
Why do we need to add a '\0' (null) at the end of a character array in C?
(9 answers)
Closed 4 years ago.
This is a program that's supposed to read inputs, a number 'n' and a character, and then duplicate this character n times. It works perfectly fine, but when I enter a large number, 8+ for example, it duplicates perfectly but then adds garbage values to the end. I can't get why it does that since I used malloc and I have exactly n blocks saved for me in the memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* create_string (char ch, int n);
void main ()
{
int n;
char ch;
printf("Enter number for duplicates: ");
scanf("%d",&n);
printf("Enter a letter: ");
scanf(" %c", &ch);
printf("The letter '%c' duplicated %d times is: ",ch,n);
char* ptr=create_string(ch,n);
printf("%s",ptr);
}
char* create_string (char ch, int n)
{
char* dup=(char*)malloc(n*sizeof(char));
int i;
for (i=0; i<n; i++)
{
dup[i]=ch;
}
return dup;
}
Test run:
Strings in C are as simple as null-terminated character sequences. That means whenever you create a string by hand, you must always append a '\0' at the end so other functions like printf know where it ends:
char* create_string (char ch, int n)
{
char* dup = malloc((n+1) * sizeof(char));
int i;
for (i=0; i<n; i++)
{
dup[i]=ch;
}
// This is important
dup[n] = '\0';
return dup;
}
Another subtle thing to notice is that because you need to store that terminating null character, you also need to reserve the space for it. So the malloc line is changed into:
malloc((n+1)*sizeof(char))
// ^^^^^ it's no longer 'n'
On a side note, you don't need to cast the returned pointer of malloc.
Strings in C are char arrays where the character \0 denotes the end of the string. Since you aren't explicitly adding it, printf just prints values from memory until it happens to run in to a terminating character (i.e., this is undefined-behavior). Instead, you should explicitly add this character to your result string:
char* create_string (char ch, int n)
{
char* dup = (char*) malloc((n + 1) * sizeof(char));
/* Added 1 for the '\0' char ---^ */
int i;
for (i = 0; i < n; i++)
{
dup[i]=ch;
}
/* Set the terminating char */
dup[n] = '\0';
return dup;
}

C standard library function 'strncpy' not working

C code:
#include<stdio.h>
#include<string.h>
#define STRINGS 10
#define STR_LEN 20
int main(void)
{
char words[STRINGS][STR_LEN];
char input[STR_LEN];
int i;
int mycount;
for(i = 0;i < STRINGS;++i;)
{
printf("Enter a word (or 0 to quit)\n:");
scanf("%19s", input);
if(input[0] == '0') break;
strncpy(words[i], input, STR_LEN);
mycount++;
}
printf("A total of %d strings were entered!\n",mycount);
}
problem: When I run this code and enter some strings it doesn't print out the amount of strings I entered
enter image description here
You need to initalize mycount to 0.
int mycount =0;
The variable mycount is uninitialized. You then attempt to modify it in the for loop via the ++ operator. So you're reading garbage values and writing garbage values. This explains the output you're getting.
Reading an uninitialized variable invokes undefined behavior. In this case, it manifests as garbage values, but it could just as easily output the expected value or cause a crash.
Initialize this variable at the time it is declared.
int mycount = 0;

C: Format %s expects argument of type char* in funny strings program

I am making a program to check for funny strings. To understand the exercise read this.
My code is here:
#define MAX_STR_LENGTH 10
char* reverse(char *str) {
char *reversedStr = malloc(strlen(str));
for (int i = 0; i < MAX_STR_LENGTH; i++) {
for (int j = MAX_STR_LENGTH - 1; j > 0; j--) {
reversedStr[i] = str[j];
}
}
return reversedStr;
}
int isFunny(char *str, char *reversedStr) {
for (int i = 1; i < MAX_STR_LENGTH; i++) {
if (str[i] - str[i - 1] != reversedStr[i] - reversedStr[i - 1]) {
return 0;
}
}
return 1;
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int numberOfStrings;
scanf("%i", &numberOfStrings);
char **strings;
for (int i = 0; i < numberOfStrings; i++) {
scanf("%s", &strings[i]);
}
char **reversedStrings;
for (int i = 0; i < numberOfStrings; i++) {
reversedStrings[i] = reverse(strings[i]);
}
for (int i = 0; i < numberOfStrings; i++) {
if (isFunny(strings[i], reversedStrings[i])) {
printf("Funny\n");
}
printf("Not funny\n");
}
return 0;
}
The error I am getting is the following:
solution.c: In function 'main':
solution.c:35:9: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char **' [-Wformat=]
scanf("%s", &strings[i]);
I don't understand why though.
My aim was to make an array of strings, called strings, and store there all the strings that I read. Why is strings[i] a char** ?
I would appreciate any help or tips.
Thanks!
Apparently you have a char * and you are passing it's address, which is wrong, scanf() wants a char pointer for each "%s" specifier, and the fix for your code is to use
char string[10];
scanf("%s", string);
the array automatically becomes a char pointer when passed to scanf() like above, but that's not enough.
Your array of char now as I suggest it is of fixed size, and even if it wasn't, using scanf() like that is dangerous, suppose that each array in the array of char arrays has 10 elements, then each string you want to read must have only 9 characters, you can instruct scanf() to stop reading when it already read 9 characters like this
scanf("%9s", strings[i]);
If you don't do this, then reading extra characters will be possible, but illegal, causing what's called undefined behavior.
If you want an array of strings, say of 5 strings with 9 characters each, then you can try
char strings[5][10];
int i;
for (i = 0 ; i < 5 ; ++i)
scanf("%9s", strings[i]);
Note: You need the & address of operator for example, when you pass an int value, because scanf() modifes the data pointed to by the passed pointer, so you need to make a pointer to the int variable where you want to scan the value, for that you use the & address of operator, since you pass a pointer containing the address of the variable.
Suggestion: Always check the return value of malloc(), it returns NULL on failure, and dereferencing a NULL poitner, is undefined behavior, you must be careful not to cause undefined behavior because it's too hard to debug.

Resources