Read string with scanf() without knowing the length [duplicate] - c

This question already has answers here:
How can I read an input string of unknown length?
(11 answers)
Closed 8 months ago.
I want to read a string (str) from the user and a number (num) via scanf() but I don't know how to initialize str correctly.
int main(void)
{
char *str = NULL;
int num;
scanf("%s %d", str, &num);
printf("str: %s\nnum: %d\n", str, num);
}
If I do it like this I get a segmentation fault.
My problem is that I don't know the length of str so I can't say something like this:
char str[20];
and I'm also not allowed to hardcode some high amount of index e.g.:
char str[999];
My question now: How can I initialize str in this case?

Some implementations provide for a %ms specifier to allocate memory as required by the POSIX specification of scanf(). Even some Unix-like systems (e.g. macOS Monterey 12.x and earlier) do not provide it.
If that is available (check the manual), this will work.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *str = NULL;
int num;
scanf("%ms %d", &str, &num);
printf("str: %s\nnum: %d\n", str, num);
free(str);
return 0;
}
To capture a string that includes space and tab, but no digits,
scanf("%m[^\n0123456789] %d", &str, &num);
could be used

Related

why passing a char* argument to gets instead of a static array of char doesn't work? [duplicate]

This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Why doesn't my program take input inspite of the fgets part? Any other suggestions are welcome
(1 answer)
Using scanf and fgets in the same program?
(4 answers)
fgets doesn't work after scanf [duplicate]
(7 answers)
Closed 1 year ago.
I atentionally keep optional details for a best undersanding. say we want to store a string in a variable of char* :
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char * s;
int n;
do{
printf("string's length: ");
scanf("%d", &n);
}while(n<=0);
s = (char *) malloc((n+1) * sizeof(char));
if(s!=NULL){
printf("enter a string (length <= %d): ", n);
gets(s);
puts(s);
free(s);
}
puts("end of programme.\n");
return 0;
}
in this answer it says :
If you were to set s to point to a preexisting array or if you used malloc to allocate space, then you can write to it successfully.
so, despite all that, why the call to gets still doesn't success? how can we explain this behavior ?
The problem is that gets read the the buffer until a line break (\n), when you input a number, you press enter to confirm it, and the \n goes to the buffer. The gets read it and assume that's what you want. You need to throwaway the line breaker before call gets.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
char * s;
int n;
do{
printf("string's length: ");
scanf("%d", &n);
}while(n<=0);
scanf("%*c"); // throwaway a character, in this case, the line breaker
s = (char *) malloc((n+1) * sizeof(char));
if(s!=NULL){
printf("enter a string (length <= %d): ", n);
gets(s);
puts(s);
free(s);
}
puts("end of programme.\n");
return 0;
}

How can I put a user input value into strncpy?

So, I am trying to write an strncpy function. I want user to input the number of characters to be copied from source. I am doing something wrong, but I can't understand what. This is what I tried to do:
#include <stdio.h>
#include <string.h>
#define ARR_SIZE 20
int main() {
char string[ARR_SIZE];
int n, m;
char s1[4], s2[4], nstr[m];
printf("Enter the string:");
gets(string);
printf("The length of the string is: %ld\n", strlen(string));
strcpy(s1, s2);
printf("The original string is: %s\n", string);
printf("The copy of the original string is: %s\n", string);
printf("How many characters do you want to take from this string to create another string? Enter: \n");
scanf("%d", &n);
strncpy(nstr, s1, m);
printf("%s\n", nstr);
}
(On top I tried some strlen and strcpy functions.)
EDIT: I totally forgot to write what was the problem. Problem is I can't get the new string which is named nstr in my code. Even though I printed it out.
first of all, the whole code is just a bad practice.
Anyway, here is my take on your code which copies n characters of an input string to string_copy
#include <stdio.h>
#include <string.h>
#define ARR_SIZE 20
int main() {
char string[ARR_SIZE];
int n;
printf("Enter the string:");
gets(string);
printf("The length of the string is: %ld\n", strlen(string));
printf("The original string is: %s\n", string);
printf("How many characters do you want to take from this string to
create another string? Enter: \n");
scanf("%d", &n);
if(n > strlen(string)){
n = strlen(string);
printf("you are allowed to copy maximum of string length %d\n", n);
}
char string_copy[n];
strncpy(string_copy, string, n);
printf("%s\n", string_copy);
}
note that using deprecated functions such as gets() isn't safe. use scanf() or fgets() instead.
refer to why you shouldn't use gets()

Creating a function to ask question from the user using scanf in C

I'm very new to C but am trying to make a function to ask the user a question using scanf, any suggestions of how I should go about this, this is currently what I have.
#include <stdio.h>
char name[100];
int num, days;
int askQ(char *question, char *x, char *answer) {
printf("%s", question);
fflush(stdout);
scanf(x,&answer);
return 1;
}
int main() {
askQ("hello? | ", "%s\n", &name);
printf("%s", name);
return 0;
}
A couple of things make this a bit tricky. Your requirement for an arbitrary format string makes it difficult to know how arguments are to be passed to scanf(). E.g. an int argument will require that you pass the address of the receiving variable to scanf(), whereas a string does not require the address because the "string" is already a pointer.
Similarly you should check the return value from scanf() to ensure that the input was processed as expected - that's hard for an arbitrary format string.
Perhaps, if you really need arbitrary input parsing you can use vscanf(), but at your level I would not recommend that.
If you choose to keep it simple so that you simply have a prompt with a single string response then you might do this:
#include <stdio.h>
int askQ(char *question, char *format, char *answer) {
printf("%s", question);
int i = scanf(format, answer);
return i == 1;
}
int main() {
char name[100]; // accept up to 100 chars input
if (askQ("hello? | ", "%s", name))
printf("Response: %s\n", name);
else
printf("Failed to get valid response from user\n");
}

C - Dynamic Memory Allocation [duplicate]

This question already has answers here:
fgets instructions gets skipped.Why?
(3 answers)
Closed 6 years ago.
#include<stdio.h>
#include<malloc.h>
int main()
{
char *string1;
int length;
scanf("%d", &length);
string1 = (char *)malloc(sizeof(char) * length);
printf("\n Enter the First String : ");
fgets(string1, length, stdin);
printf("\n The First String : %s ",string1);
free(string1);
return 0;
}
Can someone help me on the above code ? I trying to get the length of a string and the string as inputs. But, I am able to enter only Length of the string. After that it skips the string input part.
This is the output I am getting :
sh-4.3$ main
10
Enter the First String :
The First String :
sh-4.3$
After typing "10<enter>" the <enter> or "\n" will remain in the
stdin buffer, so you have to use getchar() after the scanf to
remove it.
Also you should #include <stdlib.h> instead of malloc.h.
You malloc 1 character too less, because of the 0-terminator.
string1 = malloc(length + 1); will do the job, the cast is not
necessary and sizeof(char) is always 1.
If you need to use stdin for string input you can use fgetln. I edited you example and now it looks like that:
#include<stdio.h>
#include <stdlib.h>
int main()
{
char *string1;
size_t length;
//scanf("%d", &length);
//string1 = (char *)malloc(sizeof(char) * length);
printf("\n Enter the First String : ");
//fgets(string1, length, stdin);
string1 = fgetln(stdin, &length);
string1[length] = '\0';
printf("\n The First String : %s ",string1);
free(string1);
return 0;
}
Note: fgetln returns not a C string, you should add a NULL character to the end.
The most simple answer when reading from STDIN/keyboard with the newline etc.
is to just add the "\n" to the scanf, ie:
scanf("%d\n", &length);
Solves the problem ;)
PS: Beware of all the other security/buffer overflow issues of scanf

Safely get string input from user including spaces [duplicate]

This question already exists:
Safe Alternative to gets [duplicate]
Closed 8 years ago.
I know that I can use gets(char *) to get string input from user with spaces included but I read that buffer overflow problem. Using strcpy, strcmp (and a few other functions) is not safe we should use strncpy, strncmp and explicitly mention the size of the input. Some guy on Stack Overflow told me that. So, I am worried about using gets for getting input from user or it's safe? If it's safe tell me I'll continue using it. If not then what is the other way getting spaced string input from user safely?
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a[2];
char b[] = "first";
char c[] = "second";
int s1; //,s2;
// printf("\nLong you want your %s string to be: \n",b);
//scanf("%d",&s1); fflush(stdin);
//printf("\nLong you want your %s string to be: \n",c);
// scanf("%d",&s1); fflush(stdin);
int i;
for(i=0; i<2; i++) {
printf("\nLong you want your %s string to be: \n",b);
scanf("%d",&s1); fflush(stdin);
a[i] = (char *) malloc(s1*sizeof(char));
}
printf("\nEnter the first string: \n");
scanf("%s", a[0]); fflush(stdin);
printf("\nEnter the second string: \n");
scanf("%s", a[1]); fflush(stdin);
printf("\nThe first string is: %s\n", a[0]);
printf("\nThe second string is: %s\n", a[1]);
}
Please do some research.. this http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1044652485&id=1043284385 may help you.

Resources