Safely get string input from user including spaces [duplicate] - c

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.

Related

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

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

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()

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

Why is the & operator used after using scanf? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
char string = "default";
printf("The default String is: %s", &string);
scanf("%s", &string);
printf("You entered: %s", &string);
The first printf statement prints out &string as X(?_?. The second printf, after the scanf statement prints out the string I entered.
Since the &var operator means "memory address of var", then why does &string print out the string entered? Why do I get a segmentation fault, when I attempt to use just "string"?
You have declared string as a single character but you fill it with a string. This invokes undefined behavior. You should change your code to :
char string [20] = "default"; //20 is random, you should use the maximum length of the input you may have
printf("The default String is: %19s", string);
scanf("%s", string);
printf("You entered: %s", string);
In general, scanf needs to take a memory address as an argument, and in the code above, string is a memory address. You can read more about scanf in this link.
#include <stdio.h>
#include <string.h>
char chomp(char* s, char c){
size_t l = strlen(s);
if (!l) return 0;
return s[l-1] = s[l-1]==c ? '\0' : s[l-1];
}
int main(){
char string[] = "default"; /* sizeof(string) == strlen("default")+1 */
printf("The default String is: %s\n", string);
//^ you want the array to decay to a char* here
/*scanf("%s", &string); -- DANGEROUS
-- scanf doesn't know how much space you have in string*/
fgets(string /*decay again*/, sizeof(string), stdin);
/* fgets does know because you've told it with sizeof(string)*/
chomp(string, '\n');
printf("You entered: %s", string);
return 0;
}
This would be a solution:
char string[20];
strcpy(string, "default");
printf("The default String is: %s", string);
scanf("%19s", string);
printf("You entered: %s", string);

Reverse of a string using pointers without using string handling functions? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I have updated the code as per the comments. As I am not near a PC, could you please check it and update me on that?
#include<stdio.h>
int main()
{
char s[100],rev[100],*ps1,*ps2,temp,*ptemp=&temp;
int i,n=0;
printf("Enter a string: ");
scanf("%s",s);
printf("The string is: %s\n",s);
for(i=0;s[i]!='\0';i++)
n++;
ps1=&s[0];
ps2=&s[n-1];
for(i=0;i<n/2;i++)
{
*ptemp=*ps1;
*ps1=*ps2;
*ps2=*ptemp;
*ps2--;
*ps1++;
}
printf("The reverse of the string is: %s\n",s);
}
Trying to keep code the closer to yours and making it works:
#include<stdio.h>
int main()
{
char s1[100], rev[100], *ps1=s1, *prev=rev;
int value1, value2 = 0;
int *i = &value1, *length = &value2; // Why the hell do you need pointers? But if you do want them, use them the right way
printf("Enter a string: ");
scanf("%99s", s1); // parameter must be a 'char *', not a 'char **'
printf("The string is: %s\n",s1); // Ends line with \n
for(*i=0;*(ps1+(*i))!='\0';(*i)++)
{
(*length)++;
}
printf("The length is: %d\n", *length);
for(*i=1;*(ps1+(*i)-1)!='\0';(*i)++)
{
*(prev+(*i)-1)=*(ps1+(*length)-(*i));
}
*(rev+(*i)-1)='\0';
printf("\nThe reverse string is: %s\n",rev); // Ends line with \n
}
But I must confess your last loop is really hard to understand. Also, why do you need those pointers?
Edit: Also you should check return value of scanf() is 1. Because if is is not, it means scanf() did not set a value to s1.
Edit 2: Correction of the new version of the question
#include<stdio.h>
int main()
{
char s[100],*ps1,*ps2,temp,*ptemp=&temp; // removing unused rev
int i,n=0;
printf("Enter a string: ");
scanf("%s",s);
printf("The string is: %s\n",s);
for(i=0;s[i]!='\0';i++)
n++;
ps1=&s[0]; // ps1 = s; would be fine
ps2=&s[n-1]; // ps2 = s + (n-1); would be fine
for(i=0;i<n/2;i++)
{
*ptemp=*ps1;
*ps1=*ps2;
*ps2=*ptemp;
ps2--; // You want ps2 point to previous character
ps1++; // You want ps1 point to next character
}
printf("The reverse of the string is: %s\n",s);
}
The first problem I see is that scanf expects a pointer, but you give it a pointer to a memory address which is effectively a pointer to pointer:
scanf("%s", &s1);
Should be changed to:
char s1[100] = {0};
scanf("%s", s1);
As scanf does not check for memory overflow, it would be a wiser choice to make use of this syntax over the above suggested one
char s1[100] = {0};
scanf("%99s", s1);
This way, you don't get into any buffer overflow issues
Next problem, you dereference a pointer before assigning it a valid location in memory:
for(*i=0;*(ps1+(*i))!='\0';(*i)++)
Change to:
int i;
for(i = 0; ps1[i] != '\0'; i++)
Do the same for your other for-loop
Finally, remove this line:
*(rev+(*i)-1)='\0';
And change the print statement to:
printf("\nThe reverse string is: %s",s1);

Resources