Passing argument 2 of strcmp makes pointer from integer without a cast - c

void viewonechar(){
char name[25], c[25];
int n;
fp = fopen("Phonebook.txt","r");
printf ("\n\n Enter Character : ");
scanf ("%s",c);
fscanf (fp, "%s %d", name, &n);
while (!feof(fp)){
if ((strcmp(c, name[0])) == 0){ \\ Warning in here
printf (" %s +880%d\n",name, n);
}
fscanf (fp, "%s %d", name, &n);
}
printf ("\n\n");
fclose(fp);
menu();
}
When i compile the code, on the marked line this warning appears, "Passing argument 2 of strcmp makes pointer from integer without a cast". What exactly am i doing wrong?

int strcmp ( const char * str1, const char * str2 );
Since name is an array of char, name[0] is a char. strcmp takes char pointers as an arguments, so the char you have supplied is implicitly cast to an int-type and then - to the pointer, which produces an undefined behavior and most likely will lead to the segfault.

There are a number of problems.
Avoid scanf(). See: Why does everyone say not to use scanf? What should I use instead?. Use fgets() instead. Since you are reading just one char, char c[2] is sufficient (and also will not read in the \n character).
Always do the error checking for all the standard functions.
Your loop condition is wrong. See: Why is “while ( !feof (file) )” always wrong?
You don't need to scan once outside the loop if you fix the loop.
Since you only need to compare the first chars, you can simply use c[0] == name[0].
The below code fixes the above issues:
void viewonechar(void)
{
char name[25], c[25];
int n;
FILE fp = fopen("Phonebook.txt","r");
if (!fp) {
perror("fopen");
exit(1);
}
printf ("\n\n Enter Character : ");
if (fgets(c, sizeof c, stdin) == NULL) {
fprintf(stderr, "Input error\n");
exit(1);
}
while (fscanf (fp, "%24s %d", name, &n) == 2) {
if (c[0] == name[0]) {
printf (" %s +880%d\n",name, n);
}
}
printf ("\n\n");
fclose(fp);
menu();
}

Related

How do pointers in the structure work in the following code?

I wanted to use pointer inside a struct to store 2 names the code works fine it stores and display the names as I want them to but I am confused about the role of the & operator in the scanf and printf statements when I remove the & operator from printf the names don't display. I don't know how its working.
#include <stdio.h>
int main()
{
struct name
{
char *p;
}n1,n2;
printf("ENTER NAME1\n");
scanf("%s",&n1.p);
printf("\nENTER NAME2\n");
scanf("%s",&n2.p);
printf("ENTERED NAMES ARE %s , %s",&n1.p,&n2.p);
return 0;
}
the code works fine
The code has undefined behavior because in these calls
scanf("%s",&n1.p);
scanf("%s",&n2.p);
expressions &n1.p and &n2.p have the incorrect type char ** and are overwritten.
You need to allocate memory where you are going to read strings.
printf("ENTER NAME1\n");
scanf("%s",&n1.p);
printf("\nENTER NAME2\n");
scanf("%s",&n2.p);
Where do you want to store the strings with the names into?
Into the object of the pointer p inside of the respective structure itself?
This is invalid and illegal. Pointers are made to point anywhere, not to be assigned with a value of an object they do point to themselves.
Thus to answer your question:
"How do pointers in the structure work in the following code?"
They don't work at all. Your code is a mess of undefined behavior.
You need to allocate memory first, where p is pointing to, f.e. by using malloc():
n1.p = malloc(sizeof(char) * 20); // Allocates memory for a string up to 19 characters.
if (!n1.p)
{
fputs("Error at allocation!", stderr);
return EXIT_FAILURE;
}
n2.p = malloc(sizeof(char) * 20); // Allocates memory for a string up to 19 characters.
if (!n2.p)
{
fputs("Error at allocation!", stderr);
return EXIT_FAILURE;
}
and then pass the argument to scanf() properly:
printf("ENTER NAME1\n");
scanf("%s", n1.p);
printf("\nENTER NAME2\n");
scanf("%s", n2.p);
(Note n1.p instead of &n1.p. Same goes for n2.p)
Or better:
printf("ENTER NAME1\n");
if (scanf("%s", n1.p) != 1)
{
fputs("Error at input!", stderr);
return EXIT_FAILURE;
}
printf("\nENTER NAME2\n");
if (scanf("%s", n2.p) != 1)
{
fputs("Error at input!", stderr);
return EXIT_FAILURE;
}
to ensure safety at input errors.
Furthermore the %s conversion specifier expects an argument of type char *, not pointer to char * (char **) as it is with &n1.p and &n2.p.
To provide an argument of wrong type invokes undefined behavior, too.
Just use n1.p and n2.p.
Also this printf() call is wrong:
printf("ENTERED NAMES ARE %s , %s", &n1.p,&n2.p);
You need to omit the & too:
printf("ENTERED NAMES ARE %s , %s", n1.p, n2.p);
All in one:
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
struct name
{
char *p;
} n1, n2;
n1.p = malloc(sizeof(char) * 20); // Allocates memory for a string up to 19 characters.
if (!n1.p)
{
fputs("Error at allocation!", stderr);
return EXIT_FAILURE;
}
n2.p = malloc(sizeof(char) * 20); // Allocates memory for a string up to 19 characters.
if (!n2.p)
{
fputs("Error at allocation!", stderr);
return EXIT_FAILURE;
}
printf("ENTER NAME1\n");
if (scanf("%s", n1.p) != 1)
{
fputs("Error at input!", stderr);
return EXIT_FAILUE;
}
printf("ENTER NAME2\n");
if (scanf("%s", n2.p) != 1)
{
fputs("Error at input!", stderr);
return EXIT_FAILURE;
}
printf("ENTERED NAMES ARE %s , %s", n1.p, n2.p);
free(n1.p):
free(n2.p);
return 0;
}
Execution:
ENTER NAME1
Peter
ENTER NAME2
Maria
ENTERED NAMES ARE Peter , Maria

Strings in a FOR loop

I got a question.
I want to have a FOR loop that prints back text many strings. Lets say I type my forename and last name. And a FOR loop produce the strings.
#include <stdio.h>
int main(){
char str1 [12];
char str2 [12];
char wordarray [2]={str1,str2}; // error here
int i;
printf ("Type your forname : ");
scanf ("%s",&str1);
printf ("\nType your last name : ");
scanf ("%s",&str2);
printf ("\n\nYour name is : ");
printf ("%s\t%s",str1,str2);
printf ("\n");
for (i=0;i<3;i++){
printf ("%s",wordarray [i]); // Error here .
} // end FOR
return 0;
} // end MAIN
You need to validate each read with scanf (or whatever function you use for user input) to insure you have valid data to work with. You should also provide a width limitation for the read to insure you do not read beyond the end of your array. (e.g. scanf ("%11s", str1)). You should look into using fgets for user input and remove the '\n' included by fgets in your buffer. This will help you avoid a number of pitfalls with scanf that usually plague new users, especially when taking mixed string and numeric input.
Other than that, you should also look to avoid using magic numbers in your code (e.g. char str1[12]). If you need a constant 12, then define one or declare an enum to create it.
Putting those pieces together, you could do something like:
#include <stdio.h>
#define LEN 12
int main (void) {
char str1 [LEN] = "";
char str2 [LEN] = "";
char *wordarray[] = {str1, str2};
int i, nwords = sizeof wordarray/sizeof *wordarray;
printf ("Type your forname : ");
if (scanf ("%11s", str1) != 1) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
printf ("Type your last name : ");
if (scanf ("%11s", str2) != 1) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
printf ("\nYour name is : %s %s\n", str1, str2);
for (i = 0; i < nwords; i++){
printf ("%s", wordarray [i]);
}
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/name
Type your forname : david
Type your last name : rankin
Your name is : david rankin
davidrankin
Look things over, and consider the other answers and let me know if you have further questions. Also take my comment regarding zero input or input beyond 12 characters into consideration. This will help build robustness into your input handling.
If you would like to approach the input using fgets, you can improve your input handling a bit with the following:
#include <stdio.h>
#include <string.h>
#define LEN 12
int main (void) {
char str1 [LEN] = "",
str2 [LEN] = "",
*wordarray[] = {str1, str2};
size_t i, len = 0, nwords = sizeof wordarray/sizeof *wordarray;
printf ("Type your forname : ");
if (!fgets (str1, LEN, stdin)) { /* read with fgets/validate */
fprintf (stderr, "error: invalid input.\n");
return 1;
}
len = strlen (str1); /* get length of str1 */
if (str1[len-1] == '\n') /* test for trailing '\n' */
str1[--len] = 0; /* overwrite with nulbyte */
printf ("Type your last name : ");
if (!fgets (str2, LEN, stdin)) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
len = strlen (str2);
if (str2[len-1] == '\n')
str2[--len] = 0;
printf ("\nYour name is : %s %s\n", str1, str2);
for (i = 0; i < nwords; i++){
printf ("%s", wordarray [i]);
}
putchar ('\n');
return 0;
}
You don't understand how array and pointer work. You should read this answer.
#include <stdio.h>
int main(void) {
printf("Type your forname : ");
char str1[12];
{ // we open a scope because ret don't need to be in function scope
int ret = scanf("%11s", str1); // scanf need to know how many bytes are
// available without count `\0` and you must send the array itself not the
// address
if (ret != 1) { // scanf don't set str1
fprintf(stderr, "Error in input\n"); // stderr is the error stream
return 1;
}
}
printf("\nType your last name : ");
char str2[12];
{
int ret = scanf("%11s", str2);
if (ret != 1) {
fprintf(stderr, "Error in input\n");
return 1;
}
}
printf("\n\nYour name is : ");
printf("%s\t%s", str1, str2);
printf("\n");
char *word[2] = {str1, str2}; // we need an array of pointer
for (size_t i = 0; i < sizeof word / sizeof *word; i++) { // size of array
printf("%s", word[i]);
}
return 0;
}
Shure I dont know how everything functions. That why I ask :) Thanks for the reply. I will investigate. With this information I will try to build a larger FOR-loop , so I can insert values in a 2D array. The user can add values to a 2d array then change the information text or numbers in the slots.
#include <stdio.h>
#define lenght 12 // corrected, define string format lenght
int main(){
char str1 [lenght]; // corrected, strings should have format lenght
char str2 [lenght]; // corrected, strings should have format lenght
char *wordarray [2]={str1,str2}; // corrected, add a * to wordarray[2]
int i;
printf ("Type your forname : ");
scanf ("%s",str1); // corrected, skip the & in ("%s",&str1);
printf ("Type your last name : ");
scanf ("%s",str2); // corrected, skip the & in ("%s",&str2);
printf ("\n\nYour name is : %s\t%s\n",str1,str2);
for (i=0;i<2;i++){ // corrected, i<2 must match the array elements
printf ("%s\t",wordarray [i]);
} // end FOR
return 0;
} // end MAIN
Ok. Had another go.
Havent worked much with strings. This program has both strings and numbers in arrays and printed in FOR loops. I also tried to get the indevidual elements in the arrays available to the user, so he could change the values.
I guess my style is pretty wretched. but ... its what I got.
Now concerning the GETS (str1), obtaining a string from the user. At the first use in the program it behaves normal. but the second time in the program I had to use GETS ("%s", str1) so it behaved proper. also an issue was to add specific numbers from a array detremined by the user. displayed in a for loop...
Another issue is to CLEAR the console screen after the JUMP . so the text doesnt flood the screen.
Comment : I agree David C. Rankin that validation of user data is important. Only tolerate character inputs on string requests, and numbers on integer request. Also return false input if "special characters" like slash or dots. I tried to read the origonal K&R C book and they talked about it, topics like turning all letters to small case or big case. but I had troubles getting the example code to run, maybe a C89 C11 compiler issue, I dont know.
#include <stdio.h>
//#include <string.h> // GCC32-C . mingw . compile
#define lenght 20 // Orbit_L75.Apartment_9
int main(){
int i,j,k,select,select2,*ptr;
char str1 [lenght];
char str2 [lenght];
char *wordarray [2]={str1,str2}; // character array must have a * asterix pointer .
int numarray [2];
printf ("Type your forname : ");
gets (str1); // gets (wordarray[0]) // alternative syntax
printf ("Type your last name : ");
gets (str2);
printf ("Enter your telephone number : ");
scanf ("%d",&numarray[0]); // assign a value to numarray slot 0
//scanf ("%d",(numarray+0)); // alternative syntax
printf ("Enter your age : ");
scanf ("%d",&numarray[1]); // assign a value to numarray slot 1
printf ("\n\n");
jump1 :
printf ("=========================\n");
for (i=1;i<5;i++)
{printf ("%d\t",i);}
printf ("\n");
for (j=0;j<2;j++)
{printf ("%s\t",wordarray[j]);}
//printf ("%s\t",*(wordarray+j));} // alternative syntax
printf ("\n");
for (k=0;k<2;k++)
{printf ("%d\t",numarray[k]);}
printf ("Sum = %d\n",(numarray[0]+numarray[1])); // add numarray slot 0 and slot 1.
//printf ("Sum = %d",*(numarray+0)+*(numarray+1)); // alternative syntax
printf ("=========================\n");
printf ("\n\nSelect\n1: Change Telephone \n2: Change Age \n3: Change First Name \n4: Change Last Name \n5: RAM location\n");
scanf ("%d",&select);
if (select == 1)
{printf ("New number : ");
scanf ("%d",&numarray[0]);
//scanf ("%d",(numarray+0)); // alternative syntax
printf ("\n");}
else if (select == 2)
{printf ("New age : ");
scanf ("%d",&numarray[1]);
printf ("\n");}
else if (select == 3)
{printf ("New First Name : ");
scanf ("%s",str1); //problems with the display using GETS on the second run.
printf ("\n");}
else if (select == 4)
{printf ("New Last Name : ");
scanf ("%s",str2);
printf ("\n");}
else if (select == 5)
{ // select2
{printf ("\nRAM location of : \n\t1. Telephone number\n\t2. Age\n\t3. First Name.\n\t4. Last Name\n");}
scanf ("%d",&select2);
if (select2 == 1)
{ptr = &numarray[0];
printf ("\nTelephone number\nValue in Decimal\t: %d\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 2)
{ptr = &numarray[1];
printf ("\nAge\nValue in Decimal\t: %d\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 3)
{ptr = &wordarray[0];
printf ("\nFirst Name\nValue in Text\t: %s\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 == 4)
{ptr = &wordarray[1];
printf ("\nLast Name\nValue in Text\t: %s\nValue in Hexadecimal\t: %ph\nRAM location in decimal\t: %d\nRAM location in Hex\t: %ph\n\n\n",*ptr,*ptr,ptr,ptr);}
else if (select2 <1 || select2 > 4)
{printf ("\nValue is out of range, Try again .\n\n");}
} // end IF select2
else if (select <1 || select > 5)
{printf ("\nValue is out of range, Try again .\n\n");}
goto jump1;
return 0;
} // end MAIN
str1 and str2 are effectively pointers.
wordarray is an array of chars. It should be an array of pointers to char.
Also in your scanf you're passing address of str1 and str2, but you should just pass str1 and str2.

How to read a integer followed by a string in C? [duplicate]

This question already has an answer here:
How to read / parse input in C? The FAQ
(1 answer)
Closed 6 years ago.
I am trying to write a simple program which will read two input lines, an integer followed by a string. However, it doesn't seem to work for me.
int main()
{
int i;
char str[1024];
scanf("%d", &i);
scanf("%[^\n]", str);
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
Immediately after entering the integer and pressing "Enter", the program prints the integer. It doesn't wait for me to enter the string. Whats wrong? Whats the correct way to program this?
What you need to know
The problem with %[^\n] is that it fails when the first character to be read is the newline character, and pushes it back into the stdin.
The Problem
After you enter a number for the first scanf, you press Enter. %d in the first scanf consumes the number, leaving the newline character ('\n'), generated by the Enter keypress, in the standard input stream (stdin). %[^\n] in the next scanf sees this \n and fails for the reason given in the first paragraph of this answer.
Fixes
Solutions include:
Changing scanf("%d", &i); to scanf("%d%*c", &i);. What %*c does is, it scans and discards a character.
I wouldn't recommend this way because an evil user could trick the scanf by inputting something like <number><a character>\n, ex: 2j\n and you'll face the same problem again.
Adding a space (any whitespace character will do) before %[^\n], i.e, changing scanf("%[^\n]", str); to scanf(" %[^\n]", str); as #Bathsheba mentioned in a comment.
What the whitespace character does is, it scans and discards any number of whitespace characters, including none, until the first non-whitespace character.
This means that any leading whitespace characters will be skipped when inputting for the second scanf.
This is my recommendation: Clear the stdin after every scanf. Create a function:
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
and call it after every scanf using flushstdin();.
Other issues:
Issues unrelated to your problem include:
You don't deal with the case if scanf fails. This can be due to a variety of reasons, say, malformed input, like inputting an alphabet for %d.
To do this, check the return value of scanf. It returns the number of items successfully scanned and assigned or -1 if EOF was encountered.
You don't check for buffer overflows. You need to prevent scanning in more than 1023 characters (+1 for the NUL-terminator) into str.
This can be acheived by using a length specifier in scanf.
The standards require main to be declared using either int main(void) or int main(int argc, char* argv[]), not int main().
You forgot to include stdio.h (for printf and scanf)
Fixed, Complete Program
#include <stdio.h>
void flushstdin(void)
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
int i;
char str[1024];
int retVal;
while((retVal = scanf("%d", &i)) != 1)
{
if(retVal == 0)
{
fputs("Invalid input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
while((retVal = scanf("%1023[^\n]", str)) != 1)
{
if(retVal == 0)
{
fputs("Empty input; Try again", stderr);
flushstdin();
}
else
{
fputs("EOF detected; Bailing out!", stderr);
return -1;
}
}
flushstdin();
printf("%d\n", i);
printf("%s\n", str);
return 0;
}
This simply, will work:
scanf("%d %[^\n]s", &i, str);
Instaed of scanf() use fgets() followed by sscanf().
Check return values of almost all functions with a prototype in <stdio.h>.
#include <stdio.h>
int main(void) {
int i;
char test[1024]; // I try to avoid identifiers starting with "str"
char tmp[10000]; // input buffer
// first line
if (fgets(tmp, sizeof tmp, stdin)) {
if (sscanf(tmp, "%d", &i) != 1) {
/* conversion error */;
}
} else {
/* input error */;
}
// second line: read directly into test
if (fgets(test, sizeof test, stdin)) {
size_t len = strlen(test);
if (test[len - 1] == '\n') test[--len] = 0; // remove trailing ENTER
// use i and test
printf("i is %d\n", i);
printf("test is \"%s\" (len: %d)\n", test, (int)len);
} else {
/* input error */;
}
return 0;
}

I want to make Sort program using File input/output with C language

I want to make 'Merge sort' Program.
When i started it "arr.txt" and "brr.txt" are just data and "result.txt" is result of merge sort (arr.txt+brr.txt) .
#include<stdio.h>
#include<stdlib.h>
void merge_sort(int num)
{
FILE *fp1,*fp2,*fp3; // fp1 is arr.txt, fp2 is brr.txt, and fp3 is result.txt
int i, j, point_one=0, point_two=0;
char a[num], b[num], c[num];
fp1=fopen("arr.txt","r");
fp2=fopen("brr.txt","r");
fp3=fopen("result.txt","w");
fscanf(fp1, "%s", a);
fscanf(fp2, "%s", b);
for(i=0;i<num;i++)
{
if(a[point_one]>b[point_two])
{
fprintf(fp3, b[point_two]);
point_two++;
}
else
{
fprintf(fp3, a[point_one]);
point_one++;
}
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
}
int main(void)
{
FILE *fp_one,*fp_two;
char *arr;
char *brr;
int num;
fp_one=fopen("arr.txt","w");
fp_two=fopen("brr.txt","w");
printf("input array size :");
scanf("%d", &num);
arr=(char*)malloc(sizeof(char)*num);
brr=(char*)malloc(sizeof(char)*num);
printf("input arr :" );
scanf("%s", arr);
printf("input brr :");
scanf("%s", brr);
fprintf(fp_one, arr);
fprintf(fp_two, brr);
merge_sort(num);
fclose(fp_one);
fclose(fp_two);
free(arr);
free(brr);
return 0;
}
But, in this code, I can't play sorting. Please help me
++
if array size is 5, arr.txt's contents are "acfj",and brr.txt's contents are "bdgh",
the result.txt's contents are "abcdfgh"
You have two problems. The first is that you don't print the letters correctly. The fprintf function expects the second argument to be a string, but you pass it a single character. The compiler should be screaming warnings about this to you. You should never disregard warnings, as they often are indicators of undefined behavior.
Either use e.g. fputc or use the correct format string to print a character.
The second problem, is that you don't loop enough times for the sorting/merging to be complete, as well as you never check for the end of either input.
You should close fp_one and fp_two before calling merge_sort(). Otherwise the previous output may haven't been flushed into file yet.
According to your test input, you tried to store 5 characters into 3-element character array (don't forget the '\0' character terminating a string). This leads to buffer overflow, which in turn leads to undefined behavior.
Yet another problem: in merge_sort(), when either point_one or point_two reaches the end of string, the next comparison always pick '\0' which is smaller than all other characters.
at main
change to
fprintf(fp_one, "%s", arr);//to prevent malfunction when '%' is included
fprintf(fp_two, "%s", brr);
fclose(fp_one);//to determine the output of the file.
fclose(fp_two);//Also Close to open the file in the merge_sort function.
merge_sort(num);
merge_sort change to
void merge_sort(int num){
FILE *fp1,*fp2,*fp3;
int point_one=0, point_two=0;
char a[num], b[num];
fp1=fopen("arr.txt","r");
fp2=fopen("brr.txt","r");
fp3=fopen("result.txt","w");
fscanf(fp1, "%s", a);
fscanf(fp2, "%s", b);
fclose(fp1);
fclose(fp2);
while(a[point_one] && b[point_two]){//Data of both is valid
if(a[point_one]>b[point_two]){
fprintf(fp3, "%c", b[point_two++]);
} else {
fprintf(fp3, "%c", a[point_one++]);
}
}
if(a[point_one]){//There is a rest.
fprintf(fp3, "%s", &a[point_one]);
}
if(b[point_two]){
fprintf(fp3, "%s", &b[point_two]);
}
fclose(fp3);
}

Reading in a variable length string user input in C

I am trying to read in a variable length user input and perform some operation (like searching for a sub string within a string).
The issue is that I am not aware how large my strings (it is quite possible that the text can be 3000-4000 characters) can be.
I am attaching the sample code which I have tried and the output:
char t[],p[];
int main(int argc, char** argv) {
fflush(stdin);
printf(" enter a string\n");
scanf("%s",t);
printf(" enter a pattern\n");
scanf("%s",p);
int m=strlen(t);
int n =strlen(p);
printf(" text is %s %d pattrn is %s %d \n",t,m,p,n);
return (EXIT_SUCCESS);
}
and the output is :
enter a string
bhavya
enter a pattern
av
text is bav 3 pattrn is av 2
Please don't ever use unsafe things like scanf("%s") or my personal non-favourite, gets() - there's no way to prevent buffer overflows for things like that.
You can use a safer input method such as:
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
You can then set the maximum size and it will detect if too much data has been entered on the line, flushing the rest of the line as well so it doesn't affect your next input operation.
You can test it with something like:
// Test program for getLine().
int main (void) {
int rc;
char buff[10];
rc = getLine ("Enter string> ", buff, sizeof(buff));
if (rc == NO_INPUT) {
// Extra NL since my system doesn't output that on EOF.
printf ("\nNo input\n");
return 1;
}
if (rc == TOO_LONG) {
printf ("Input too long [%s]\n", buff);
return 1;
}
printf ("OK [%s]\n", buff);
return 0;
}
In practice you shouldn't bother too much to be precise. Give yourself some slack to have some memory on the stack and operate on this. Once you want to pass the data further, you can use strdup(buffer) and have it on the heap. Know your limits. :-)
int main(int argc, char** argv) {
char text[4096];
char pattern[4096];
fflush(stdin);
printf(" enter a string\n");
fgets(text, sizeof(text), stdin);
printf(" enter a pattern\n");
fgets(pattern, sizeof(pattern), stdin);
int m=strlen(text);
int n =strlen(pattern);
printf(" text is %s %d pattrn is %s %d \n",text,m,pattern,n);
return (EXIT_SUCCESS);
}
Don't use scanf or gets for that matter because as you say, there is not real way of knowing just how long the input is going to be. Rather use fgets using stdin as the last parameter. fgets allows you to specify the maximum number of characters that should be read. You can always go back and read more if you need to.
scanf(%s) and gets read until they find a terminating character and may well exceed the length of your buffer causing some hard to fix problems.
The main problem in your case is having char arrays of unknown size. Just specify the array size on declaration.
int main(int argc, char** argv) {
int s1[4096], s2[4096];
fflush(stdin);
printf(" enter a string\n");
scanf("%s", s1);
printf(" enter a pattern\n");
scanf("%s", s2);
int m = strlen(s1);
int n = strlen(s2);
printf(" text is %s of length %d, pattern is %s of length %d \n", s1, m, s2, n);
return (EXIT_SUCCESS);
}

Resources