I tried to replace a target word in sentence to another word but it doesn't work. Can you please help me with where I got wrong? It has a problem with strstr and strncopy. It says that *swap can be zero, which then makes strncpy stop. I tried to find way to solve this problem, but I couldn't. How can I fix this code?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *swap (char* data, const char* original, const char* change);
int main() {
char string[100];
char original[100];
char change[100];
printf("Input String : ");
fgets(string, 100, stdin);
printf("Find String : ");
fgets(original, 100, stdin);
printf("Replace String : ");
fgets(change, 100, stdin);
printf("%s", swap(string, change, original));
return 0;
}
char *swap(char* data, const char* original, const char* change) {
char* swap;
swap = strstr(data, original);
int num = strlen(change);
if (num == 0 || swap==0) return 0;
strncpy(swap, change, strlen(change));
printf("Result : %s", data);
return 0;
}
I have fixed your code and added a few tests to avoid buffer overflow vulnerability in your swap function.
My version take car of change and original being of different lengths.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *swap(char* data, int size, const char* original, const char* change);
int main()
{
char string[100];
char original[100];
char change[100];
printf("Input String : ");
fgets(string, sizeof(string), stdin);
string[strcspn(string, "\r\n")] = 0; // Remove EOL
printf("Find String : ");
fgets(original, sizeof(original), stdin);
original[strcspn(original, "\r\n")] = 0; // Remove EOL
printf("Replace String : ");
fgets(change, sizeof(change), stdin);
change[strcspn(change, "\r\n")] = 0; // Remove EOL
printf("%s\n", swap(string, sizeof(string), original, change));
return 0;
}
char *swap(char* data, int size, const char* original, const char* change)
{
if ((data == NULL) || (original == NULL) || (change == NULL))
return data; // Unspecified data
int datLen = strlen(data);
int oriLen = strlen(original);
if (oriLen == 0)
return data; // No original specified
char *swap = strstr(data, original);
if (swap == NULL)
return data; // Original not found in data
int chgLen = strlen(change);
if (size < (datLen + chgLen - oriLen))
return data; // Not enough space to store result
if (chgLen != oriLen)
memmove(swap + chgLen, swap + oriLen, 1 + datLen + oriLen - (swap - data));
memmove(swap, change, chgLen);
return data;
}
I have not changed that, but I think it is better to have swap return 0 or 1 if the swap took place or not. Returning data is not very useful as the swap is done in place.
Related
If I don't know how long the word is, I cannot write char m[6];,
The length of the word is maybe ten or twenty long.
How can I use scanf to get input from the keyboard?
#include <stdio.h>
int main(void)
{
char m[6];
printf("please input a string with length=5\n");
scanf("%s",&m);
printf("this is the string: %s\n", m);
return 0;
}
please input a string with length=5
input: hello
this is the string: hello
Enter while securing an area dynamically
E.G.
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(*str)*size);//size is start size
if(!str)return str;
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(*str)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(*str)*len);
}
int main(void){
char *m;
printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
free(m);
return 0;
}
With the computers of today, you can get away with allocating very large strings (hundreds of thousands of characters) while hardly making a dent in the computer's RAM usage. So I wouldn't worry too much.
However, in the old days, when memory was at a premium, the common practice was to read strings in chunks. fgets reads up to a maximum number of chars from the input, but leaves the rest of the input buffer intact, so you can read the rest from it however you like.
in this example, I read in chunks of 200 chars, but you can use whatever chunk size you want of course.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readinput()
{
#define CHUNK 200
char* input = NULL;
char tempbuf[CHUNK];
size_t inputlen = 0, templen = 0;
do {
fgets(tempbuf, CHUNK, stdin);
templen = strlen(tempbuf);
input = realloc(input, inputlen+templen+1);
strcpy(input+inputlen, tempbuf);
inputlen += templen;
} while (templen==CHUNK-1 && tempbuf[CHUNK-2]!='\n');
return input;
}
int main()
{
char* result = readinput();
printf("And the result is [%s]\n", result);
free(result);
return 0;
}
Note that this is a simplified example with no error checking; in real life you will have to make sure the input is OK by verifying the return value of fgets.
Also note that at the end if the readinput routine, no bytes are wasted; the string has the exact memory size it needs to have.
I've seen only one simple way of reading an arbitrarily long string, but I've never used it. I think it goes like this:
char *m = NULL;
printf("please input a string\n");
scanf("%ms",&m);
if (m == NULL)
fprintf(stderr, "That string was too long!\n");
else
{
printf("this is the string %s\n",m);
/* ... any other use of m */
free(m);
}
The m between % and s tells scanf() to measure the string and allocate memory for it and copy the string into that, and to store the address of that allocated memory in the corresponding argument. Once you're done with it you have to free() it.
This isn't supported on every implementation of scanf(), though.
As others have pointed out, the easiest solution is to set a limit on the length of the input. If you still want to use scanf() then you can do so this way:
char m[100];
scanf("%99s",&m);
Note that the size of m[] must be at least one byte larger than the number between % and s.
If the string entered is longer than 99, then the remaining characters will wait to be read by another call or by the rest of the format string passed to scanf().
Generally scanf() is not recommended for handling user input. It's best applied to basic structured text files that were created by another application. Even then, you must be aware that the input might not be formatted as you expect, as somebody might have interfered with it to try to break your program.
There is a new function in C standard for getting a line without specifying its size. getline function allocates string with required size automatically so there is no need to guess about string's size. The following code demonstrate usage:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, stdin)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (ferror(stdin)) {
/* handle error */
}
free(line);
return 0;
}
If I may suggest a safer approach:
Declare a buffer big enough to hold the string:
char user_input[255];
Get the user input in a safe way:
fgets(user_input, 255, stdin);
A safe way to get the input, the first argument being a pointer to a buffer where the input will be stored, the second the maximum input the function should read and the third is a pointer to the standard input - i.e. where the user input comes from.
Safety in particular comes from the second argument limiting how much will be read which prevents buffer overruns. Also, fgets takes care of null-terminating the processed string.
More info on that function here.
EDIT: If you need to do any formatting (e.g. convert a string to a number), you can use atoi once you have the input.
Safer and faster (doubling capacity) version:
char *readline(char *prompt) {
size_t size = 80;
char *str = malloc(sizeof(char) * size);
int c;
size_t len = 0;
printf("%s", prompt);
while (EOF != (c = getchar()) && c != '\r' && c != '\n') {
str[len++] = c;
if(len == size) str = realloc(str, sizeof(char) * (size *= 2));
}
str[len++]='\0';
return realloc(str, sizeof(char) * len);
}
Read directly into allocated space with fgets().
Special care is need to distinguish a successful read, end-of-file, input error and out-of memory. Proper memory management needed on EOF.
This method retains a line's '\n'.
#include <stdio.h>
#include <stdlib.h>
#define FGETS_ALLOC_N 128
char* fgets_alloc(FILE *istream) {
char* buf = NULL;
size_t size = 0;
size_t used = 0;
do {
size += FGETS_ALLOC_N;
char *buf_new = realloc(buf, size);
if (buf_new == NULL) {
// Out-of-memory
free(buf);
return NULL;
}
buf = buf_new;
if (fgets(&buf[used], (int) (size - used), istream) == NULL) {
// feof or ferror
if (used == 0 || ferror(istream)) {
free(buf);
buf = NULL;
}
return buf;
}
size_t length = strlen(&buf[used]);
if (length + 1 != size - used) break;
used += length;
} while (buf[used - 1] != '\n');
return buf;
}
Sample usage
int main(void) {
FILE *istream = stdin;
char *s;
while ((s = fgets_alloc(istream)) != NULL) {
printf("'%s'", s);
free(s);
fflush(stdout);
}
if (ferror(istream)) {
puts("Input error");
} else if (feof(istream)) {
puts("End of file");
} else {
puts("Out of memory");
}
return 0;
}
I know that I have arrived after 4 years and am too late but I think I have another way that someone can use. I had used getchar() Function like this:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//I had putten the main Function Bellow this function.
//d for asking string,f is pointer to the string pointer
void GetStr(char *d,char **f)
{
printf("%s",d);
for(int i =0;1;i++)
{
if(i)//I.e if i!=0
*f = (char*)realloc((*f),i+1);
else
*f = (char*)malloc(i+1);
(*f)[i]=getchar();
if((*f)[i] == '\n')
{
(*f)[i]= '\0';
break;
}
}
}
int main()
{
char *s =NULL;
GetStr("Enter the String:- ",&s);
printf("Your String:- %s \nAnd It's length:- %lu\n",s,(strlen(s)));
free(s);
}
here is the sample run for this program:-
Enter the String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!!
Your String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!!
And It's length:- 67
Take a character pointer to store required string.If you have some idea about possible size of string then use function
char *fgets (char *str, int size, FILE* file);
else you can allocate memory on runtime too using malloc() function which dynamically provides requested memory.
i also have a solution with standard inputs and outputs
#include<stdio.h>
#include<malloc.h>
int main()
{
char *str,ch;
int size=10,len=0;
str=realloc(NULL,sizeof(char)*size);
if(!str)return str;
while(EOF!=scanf("%c",&ch) && ch!="\n")
{
str[len++]=ch;
if(len==size)
{
str = realloc(str,sizeof(char)*(size+=10));
if(!str)return str;
}
}
str[len++]='\0';
printf("%s\n",str);
free(str);
}
I have a solution using standard libraries of C and also creating a string type (alias of char*) like in C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
typedef struct __strstr {
char ch;
struct __strstr *next;
}Strstr;
void get_str(char **str) {
char ch, *buffer, a;
Strstr *new = NULL;
Strstr *head = NULL, *tmp = NULL;
int c = 0, k = 0;
while ((ch = getchar()) != '\n') {
new = malloc(sizeof(Strstr));
if(new == NULL) {
printf("\nError!\n");
exit(1);
}
new->ch = ch;
new->next = NULL;
new->next = head;
head = new;
}
tmp = head;
while (tmp != NULL) {
c++;
tmp = tmp->next;
}
if(c == 0) {
*str = "";
} else {
buffer = malloc(sizeof(char) * (c + 1));
*str = malloc(sizeof(char) * (c + 1));
if(buffer == NULL || *str == NULL) {
printf("\nError!\n");
exit(1);
}
tmp = head;
while (tmp != NULL) {
buffer[k] = tmp->ch;
k++;
tmp = tmp->next;
}
buffer[k] = '\0';
for (int i = 0, j = strlen(buffer)-1; i < j; i++, j--) {
a = buffer[i];
buffer[i] = buffer[j];
buffer[j] = a;
}
strcpy(*str, buffer);
// Dealloc
free(buffer);
while (head != NULL) {
tmp = head;
head = head->next;
free(tmp);
}
}
}
int main() {
string str;
printf("Enter text: ");
get_str(&str);
printf("%s\n", str);
return 0;
}
Here is the demo code I am using to construct string from char arrays, Is there any better way to construct String *RV200# *FV200# ??
int main()
{
char String4H1[10] = "*FV";
char String4H3[10] = "*RV";
char String4H2[10] = "#";
char data1[10];
char data2[10];
snprintf(data1,4, "%03d", 200); //Convert integer to string function
snprintf(data2,4, "%03d", 200); //Convert integer to string function
ConvertToString(String4H1,data1, 3); //*FV200
ConvertToString(String4H3,data2, 3); //*RV200
ConvertToString(String4H1,String4H2,6); //*FV200#
ConvertToString(String4H3,String4H2,6); //*RV200#
//Display String4H1 And String 4H3
}
void ConvertToString(char subject[], const char insert[], int pos)
{
char buf[100] = {};
strncpy(buf, subject, pos); // copy at most first pos characters
int len = strlen(buf);
strcpy(buf+len, insert); // copy all of insert[] at the end
len += strlen(insert); // increase the length by length of insert[]
strcpy(buf+len, subject+pos); // copy the rest
strcpy(subject, buf); // copy it back to subject
// deallocate buf[] here, if used malloc()
}
The number 200 is not known at the start of the program, it is fetched from memory using the IDE function to get value from particular memory address.
like this :-
unsigned short BUF = GetWord(#FrontVIB#,0);
unsigned short BUF1 = GetWord(#RearVIB#,0);
//BUF and BUF1 stores the value of address #FrontVIB# and #RearVIB# respectively
**structure** :-
unsigned short GetWord( #Address Alias#, Address Offset );
That's a simple example. Probably I'll be down-voted :)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
bool concatenateString(char **dest, size_t *size, char *stringToAdd)
{
bool retVal = true;
char *dest_old = *dest;
*size += strlen(stringToAdd);
if (*dest == NULL)
{
*size += 1; // to add null terminator of string
*dest = calloc(1, size);
}
else
{
*dest = realloc(*dest, size);
}
if (dest == NULL)
{
free(dest_old);
retVal = false;
}
else
{
strcat(*dest, stringToAdd);
}
return retVal;
}
int main()
{
char newString[32] = {0};
int number;
size_t size = 0;
char *data1 = NULL;
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(&data1, &size, newString))
{
printf("Insert a number:");
scanf(" %d", &number);
sprintf(newString, "%03d", number);
if (concatenateString(&data1, &size, newString) )
{
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(&data1, &size, newString))
printf("%s\n", data1);
}
}
free(data1);
}
Without using dynamic allocation
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
bool concatenateString(char *dest, size_t size_of_dest, char *stringToAdd)
{
bool retVal = true;
size_t new_size = strlen(dest) + strlen(stringToAdd);
if (new_size < size_of_dest)
{
strcat(dest, stringToAdd);
}
else
{
retVal = false;
}
return retVal;
}
int main()
{
char result[128] = {0};
char newString[32] = {0};
int number;
printf("Insert a string:");
scanf(" %s", newString);
printf("%s\n", newString);
if (concatenateString(result, sizeof(result), newString))
{
printf("Insert a number:");
scanf(" %d", &number);
sprintf(newString, "%03d", number);
if (concatenateString(result, sizeof(result), newString) )
{
printf("Insert a string:");
scanf(" %s", newString);
if (concatenateString(result, sizeof(result), newString))
printf("%s\n", result);
}
}
}
INPUT
Insert a string: *RV
Insert a number: 200
Insert a string: #
OUTPUT
*RV200#
A number of issues, I am only tackling ConvertToString()
Although some attempts made at coping with string buffer issues, too many holes exist in OP's code. Consider the following.
void ConvertToString(char subject[], const char insert[], int pos) {
char buf[100] = {};
strncpy(buf, subject, pos); // copy at most first pos characters
int len = strlen(buf);
...
What is the impact of pos == 100?
strlen(buf) may attempt to find the length of a character array with no null character --> UB.
What is the impact of pos > 100?
strncpy() attempts to write data outside the bonds of buf.
Pedantic: What is the impact of pos < 0?
strncpy() attempts to write data outside the bonds of buf as pos is converted into an excessive large unsigned number.
Concerning strcpy(buf+len, subject+pos);
What is the impact if pos exceeds strlen(subject)
UB as code attempts to read outside subject.
Re-write attempt. The key elements: include the size available for the expanded subject is passed in and determine string lengths. Then test for acceptability. After all that, shift the end of subject to make room for insert.
void ConvertToString(char subject[], size_t subject_size, const char *insert,
size_t pos) {
size_t insert_length = strlen(insert);
size_t subject_length = strlen(subject);
// Insure pos does not exceed subject_length,
// this critical part missing in OP code
if (pos > subject_length) {
pos = subject_length;
}
// Insure we have enough space
size_t buf_size = subject_length + insert_length + 1;
if (buf_size > subject_size) {
Handle_Insufficent_subject_size();
return;
}
// Move end portion of `subject` over to the right `insert_length` places.
memmove(subject + pos + insert_length, subject + pos, subject_length - pos + 1);
memcpy(subject + pos, insert, insert_length); // copy insert
}
I'm trying to make a simple user and password autentication in C.
I was told to never use gets() when getting input and I should use fgets() instead.
But I'm not sure of how the fgets() works or why is giving me this input.
Here is the code.
#include <stdio.h>
#include <string.h>
int login(char *user, char *passwd){
int enter = 0;
char p[6];
char u[6];
printf("User: ");
fgets(u, sizeof u, stdin);
printf("Pass: ");
fgets(p, sizeof p, stdin);
printf("%s\n", p);
if (strcmp(user, u) == 0 && strcmp(passwd, p) == 0){
enter = 1;
}
return entrar;
}
int main(){
char user[] = "admin";
char passwd[] = "12345";
if (login(user, passwd)){
puts("--ACCESS GRANTED--");
}
else{
puts("--Wrong pass or user--");
}
return 0;
}
Ouput
User: admin
Pass:
--Wrong pass or user--
It doesn't even let me enter the password after I press enter.
The problem here is the size of your char[], if you set it to 6, 'admin' will overflow, as reading with gets will read some extra characters.
Try with a bigger string, I'm sure you can afford it, say:
char u[10];
char p[10];
And that is still a quite stingy ;)
well.. you had two problems
one as suggested here, you should change the size of u and p to 10, the other is, the fgets also fetches the new line \n that you need to remove before comparing the strings.
so the complete answer would be:
#include <stdio.h>
#include <string.h>
int login(char *user, char *passwd){
int enter = 0;
char p[10];
char u[10];
char *pos;
printf("User: ");
fgets(u, sizeof u, stdin);
if ((pos=strchr(u, '\n')) != NULL) {
*pos = '\0';
}
printf("'%s'\n", u);
printf("Pass: ");
fgets(p, sizeof p, stdin);
if ((pos=strchr(p, '\n')) != NULL) {
*pos = '\0';
}
printf("'%s'\n", p);
if (strcmp(user, u) == 0 && strcmp(passwd, p) == 0){
enter = 1;
}
return enter;
}
int main(){
char user[] = "admin";
char passwd[] = "12345";
if (login(user, passwd)){
puts("--ACCESS GRANTED--");
}
else{
puts("--Wrong pass or user--");
}
return 0;
}
I'm trying to scan user input text for specific words and then, when those words occur, print them to the console.
#import <Foundation/Foundation.h>
#include <stdio.h>
int main(){
char cArray[] = "example";
char cInput[] = "";
char cOutput[] = "";
printf("\nType your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, 120, stdin);
}
printf("\nInitialised character array:\n");
for (int x=0; x<1; x++){
if(strncmp(&cInput[x], &cArray[x], 120) == 0){
strncpy(cOutput, cArray, strnlen(cInput, +1));
printf("%s\n", cOutput);
break;
}
}
}
Output:
Type your message:
example
Initialised character array:
Program ended with exit code: 120
Appreciate any feedback as I'm still learning :)
Thanks.
The edited code:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char *cArray[MAX_STR_LEN] = {"example", "this"};
char cInput[MAX_STR_LEN] = "";
char cOutput[MAX_STR_LEN] = "";
printf("Type your message:\n");
for (int y=0; y<1; y++){
fgets(cInput, MAX_STR_LEN, stdin);
char * ptr = cInput;
while((ptr=strstr(ptr, *cArray)) != NULL){
strncpy(cOutput, ptr, strlen(*cArray));
printf("Initialised string array:\n%s\n", cOutput);
ptr++;
}
}
}
Works although I'm encountering a different problem now. The output only seems to register one word before it completes, thus only "example" is printed.
Output:
Type your message:
this is an example
Initialised string array:
example
Program ended with exit code: 0
char cInput[] = "";
The sizeof this array is 1.
fgets(cInput, 120, stdin);
This is array out of bound write which will lead to undefined behavior.
Have
char cInput[120] = "";
You need to take care of
char cOutput[120] = "";
also. Since you are trying to write to this array after comparing.
You need strstr function from string.h
const char * strstr ( const char * str1, const char * str2 );
the following gives you an example of usage:
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 120
int main(){
char cArray[MAX_STR_LEN] = "example"; // string to be searched in the input string
char cInput[MAX_STR_LEN] = ""; // input string
char cOutput[MAX_STR_LEN] = ""; // buffer for found string
printf("\nType your message:\n");
for (int y=0; y<1; y++){ // this loop from original example looks strange, but it works
fgets(cInput, MAX_STR_LEN, stdin);
}
// search in the input string
char * ptr;
if( ( ptr=strstr(cInput, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String that was found: \n%s\n", cOutput);
}
else
{
printf("String was not found in the input!\n");
}
}
EDIT:
If you want to all the strings, use the following loop instead of if-else:
// search in the input string
char * ptr = cInput;
while( ( ptr=strstr(ptr, cArray) ) != NULL)
{
//copy the string to cOutput
strncpy(cOutput, ptr, strlen(cArray));
// output the found string
printf("String \"%s\" was found at position %d\n", cOutput, (int)(ptr - cInput + 1));
// find next string
ptr++;
}
If I don't know how long the word is, I cannot write char m[6];,
The length of the word is maybe ten or twenty long.
How can I use scanf to get input from the keyboard?
#include <stdio.h>
int main(void)
{
char m[6];
printf("please input a string with length=5\n");
scanf("%s",&m);
printf("this is the string: %s\n", m);
return 0;
}
please input a string with length=5
input: hello
this is the string: hello
Enter while securing an area dynamically
E.G.
#include <stdio.h>
#include <stdlib.h>
char *inputString(FILE* fp, size_t size){
//The size is extended by the input with the value of the provisional
char *str;
int ch;
size_t len = 0;
str = realloc(NULL, sizeof(*str)*size);//size is start size
if(!str)return str;
while(EOF!=(ch=fgetc(fp)) && ch != '\n'){
str[len++]=ch;
if(len==size){
str = realloc(str, sizeof(*str)*(size+=16));
if(!str)return str;
}
}
str[len++]='\0';
return realloc(str, sizeof(*str)*len);
}
int main(void){
char *m;
printf("input string : ");
m = inputString(stdin, 10);
printf("%s\n", m);
free(m);
return 0;
}
With the computers of today, you can get away with allocating very large strings (hundreds of thousands of characters) while hardly making a dent in the computer's RAM usage. So I wouldn't worry too much.
However, in the old days, when memory was at a premium, the common practice was to read strings in chunks. fgets reads up to a maximum number of chars from the input, but leaves the rest of the input buffer intact, so you can read the rest from it however you like.
in this example, I read in chunks of 200 chars, but you can use whatever chunk size you want of course.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* readinput()
{
#define CHUNK 200
char* input = NULL;
char tempbuf[CHUNK];
size_t inputlen = 0, templen = 0;
do {
fgets(tempbuf, CHUNK, stdin);
templen = strlen(tempbuf);
input = realloc(input, inputlen+templen+1);
strcpy(input+inputlen, tempbuf);
inputlen += templen;
} while (templen==CHUNK-1 && tempbuf[CHUNK-2]!='\n');
return input;
}
int main()
{
char* result = readinput();
printf("And the result is [%s]\n", result);
free(result);
return 0;
}
Note that this is a simplified example with no error checking; in real life you will have to make sure the input is OK by verifying the return value of fgets.
Also note that at the end if the readinput routine, no bytes are wasted; the string has the exact memory size it needs to have.
I've seen only one simple way of reading an arbitrarily long string, but I've never used it. I think it goes like this:
char *m = NULL;
printf("please input a string\n");
scanf("%ms",&m);
if (m == NULL)
fprintf(stderr, "That string was too long!\n");
else
{
printf("this is the string %s\n",m);
/* ... any other use of m */
free(m);
}
The m between % and s tells scanf() to measure the string and allocate memory for it and copy the string into that, and to store the address of that allocated memory in the corresponding argument. Once you're done with it you have to free() it.
This isn't supported on every implementation of scanf(), though.
As others have pointed out, the easiest solution is to set a limit on the length of the input. If you still want to use scanf() then you can do so this way:
char m[100];
scanf("%99s",&m);
Note that the size of m[] must be at least one byte larger than the number between % and s.
If the string entered is longer than 99, then the remaining characters will wait to be read by another call or by the rest of the format string passed to scanf().
Generally scanf() is not recommended for handling user input. It's best applied to basic structured text files that were created by another application. Even then, you must be aware that the input might not be formatted as you expect, as somebody might have interfered with it to try to break your program.
There is a new function in C standard for getting a line without specifying its size. getline function allocates string with required size automatically so there is no need to guess about string's size. The following code demonstrate usage:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, stdin)) != -1) {
printf("Retrieved line of length %zu :\n", read);
printf("%s", line);
}
if (ferror(stdin)) {
/* handle error */
}
free(line);
return 0;
}
If I may suggest a safer approach:
Declare a buffer big enough to hold the string:
char user_input[255];
Get the user input in a safe way:
fgets(user_input, 255, stdin);
A safe way to get the input, the first argument being a pointer to a buffer where the input will be stored, the second the maximum input the function should read and the third is a pointer to the standard input - i.e. where the user input comes from.
Safety in particular comes from the second argument limiting how much will be read which prevents buffer overruns. Also, fgets takes care of null-terminating the processed string.
More info on that function here.
EDIT: If you need to do any formatting (e.g. convert a string to a number), you can use atoi once you have the input.
Safer and faster (doubling capacity) version:
char *readline(char *prompt) {
size_t size = 80;
char *str = malloc(sizeof(char) * size);
int c;
size_t len = 0;
printf("%s", prompt);
while (EOF != (c = getchar()) && c != '\r' && c != '\n') {
str[len++] = c;
if(len == size) str = realloc(str, sizeof(char) * (size *= 2));
}
str[len++]='\0';
return realloc(str, sizeof(char) * len);
}
Read directly into allocated space with fgets().
Special care is need to distinguish a successful read, end-of-file, input error and out-of memory. Proper memory management needed on EOF.
This method retains a line's '\n'.
#include <stdio.h>
#include <stdlib.h>
#define FGETS_ALLOC_N 128
char* fgets_alloc(FILE *istream) {
char* buf = NULL;
size_t size = 0;
size_t used = 0;
do {
size += FGETS_ALLOC_N;
char *buf_new = realloc(buf, size);
if (buf_new == NULL) {
// Out-of-memory
free(buf);
return NULL;
}
buf = buf_new;
if (fgets(&buf[used], (int) (size - used), istream) == NULL) {
// feof or ferror
if (used == 0 || ferror(istream)) {
free(buf);
buf = NULL;
}
return buf;
}
size_t length = strlen(&buf[used]);
if (length + 1 != size - used) break;
used += length;
} while (buf[used - 1] != '\n');
return buf;
}
Sample usage
int main(void) {
FILE *istream = stdin;
char *s;
while ((s = fgets_alloc(istream)) != NULL) {
printf("'%s'", s);
free(s);
fflush(stdout);
}
if (ferror(istream)) {
puts("Input error");
} else if (feof(istream)) {
puts("End of file");
} else {
puts("Out of memory");
}
return 0;
}
I know that I have arrived after 4 years and am too late but I think I have another way that someone can use. I had used getchar() Function like this:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//I had putten the main Function Bellow this function.
//d for asking string,f is pointer to the string pointer
void GetStr(char *d,char **f)
{
printf("%s",d);
for(int i =0;1;i++)
{
if(i)//I.e if i!=0
*f = (char*)realloc((*f),i+1);
else
*f = (char*)malloc(i+1);
(*f)[i]=getchar();
if((*f)[i] == '\n')
{
(*f)[i]= '\0';
break;
}
}
}
int main()
{
char *s =NULL;
GetStr("Enter the String:- ",&s);
printf("Your String:- %s \nAnd It's length:- %lu\n",s,(strlen(s)));
free(s);
}
here is the sample run for this program:-
Enter the String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!!
Your String:- I am Using Linux Mint XFCE 18.2 , eclispe CDT and GCC7.2 compiler!!
And It's length:- 67
Take a character pointer to store required string.If you have some idea about possible size of string then use function
char *fgets (char *str, int size, FILE* file);
else you can allocate memory on runtime too using malloc() function which dynamically provides requested memory.
i also have a solution with standard inputs and outputs
#include<stdio.h>
#include<malloc.h>
int main()
{
char *str,ch;
int size=10,len=0;
str=realloc(NULL,sizeof(char)*size);
if(!str)return str;
while(EOF!=scanf("%c",&ch) && ch!="\n")
{
str[len++]=ch;
if(len==size)
{
str = realloc(str,sizeof(char)*(size+=10));
if(!str)return str;
}
}
str[len++]='\0';
printf("%s\n",str);
free(str);
}
I have a solution using standard libraries of C and also creating a string type (alias of char*) like in C++
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
typedef struct __strstr {
char ch;
struct __strstr *next;
}Strstr;
void get_str(char **str) {
char ch, *buffer, a;
Strstr *new = NULL;
Strstr *head = NULL, *tmp = NULL;
int c = 0, k = 0;
while ((ch = getchar()) != '\n') {
new = malloc(sizeof(Strstr));
if(new == NULL) {
printf("\nError!\n");
exit(1);
}
new->ch = ch;
new->next = NULL;
new->next = head;
head = new;
}
tmp = head;
while (tmp != NULL) {
c++;
tmp = tmp->next;
}
if(c == 0) {
*str = "";
} else {
buffer = malloc(sizeof(char) * (c + 1));
*str = malloc(sizeof(char) * (c + 1));
if(buffer == NULL || *str == NULL) {
printf("\nError!\n");
exit(1);
}
tmp = head;
while (tmp != NULL) {
buffer[k] = tmp->ch;
k++;
tmp = tmp->next;
}
buffer[k] = '\0';
for (int i = 0, j = strlen(buffer)-1; i < j; i++, j--) {
a = buffer[i];
buffer[i] = buffer[j];
buffer[j] = a;
}
strcpy(*str, buffer);
// Dealloc
free(buffer);
while (head != NULL) {
tmp = head;
head = head->next;
free(tmp);
}
}
}
int main() {
string str;
printf("Enter text: ");
get_str(&str);
printf("%s\n", str);
return 0;
}