What's wrong with my code? What is argv[1]? - c

I'm trying to ask the user to type in a string so I will print the length of the string. My code is built succeeded. However, when I entered a word and pressed 'enter', the program keeps running. I had to enter a second word, then the length of the first string displays. I'm confused at argv[1]. Can someone give me some tips and hint on how to fix this? Thanks in advance for your time.
Please note that I'm not allowed to use any string function.
int main(int argc, char* argv[]){
char* s=argv[1];
char input[256];
s = input;
printf("Please enter a string: ");
scanf("%s\n", s);
int str_length = 0;
while (s[str_length] != '\0')
{
str_length++;
if (s[str_length] == '\0') break;
}
printf("%d\n", str_length);
return 0;
}

argv[] is the array that holds your command line parameters, argv[1] is the first one (other than the command representation itself in argv[0], of course). You assign it to s then immediately overwrite s, so it's not really needed here.
The reason you're having to enter two lines is the \n at the end of your input format. It requires whatever can match the format string followed by a newline, hence the %s\n is eating your first newline so that scanf has to go back for another one.
%s on it's own will fix that problem but introduce another one if what you're after is a full line of input - it will only read up to the first whitespace. For a proper line input function, see here.
It does full line input with protection against buffer overflows and detection/cleanup of lines that were too long, something sorely missing in the scanf("%s") input method.
In addition, the if statement within the while is superfluous here since the while itself will catch the end of the string, and it makes little sense to have both input and s refer to the same array (it would make sense if you changed s at some point, but that's not happening here).
So, a variant without the advanced line iput function could be as simple as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[]) {
char input[256];
int str_length = 0;
printf ("Please enter a string: ");
scanf ("%s", input);
while (input[str_length] != '\0') /* Or consider using strlen() */
str_length++;
printf ("%d\n", str_length);
return 0;
}
If you enter Hello, you'll see that it prints out 5 immediately. You'll also see 5 if you enter Hello Pax, which is one reason to choose the advanced input function (the other, very important, reason is to avoid introducing a buffer overflow vulnerability into your program).

argv is used to pass process arguments. this means you can run your program like
a.out 123 abcd
argv[1] will already be assigned to a value of 123. you do not have to read it as you are doing now. in your current code , you are overwriting the reference of s to a new string after assigning it with argv[1].

This is what you want
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX 100
int main(int argc, char* argv[]){
char tmp[MAX];
printf("Plese enter a string:\n");
scanf("%s", tmp);
printf("the length is %d\n", strlen(tmp));
return 0;
}
The argv and argc is another thing like this:
argv[0] = a.exe
argv[1] = 12345
int main(int argc, char* argv[]){
printf("the length is %d\n", strlen(argv[1]));
return 0;
}
/*-------------------- Output --------------------
> a.out 12345
the length is 5
------------------------------------------------*/

Just change the scanf line:
scanf("%s", s);
As you have it (scanf("%s\n", s);), it requires a sequnce of characters ending in \n, then another \n to indicate when the input is finished.

Related

Palindrome in C using scanf and no string library functions

the assignment is to get an input string, and using no string library functions to be able to handle the string. this code at the moment doesn't even print out the string i get in. when I remove the functions from main it magically starts to print. any help would be greatly appreciated
#include <stdio.h>
#include <string.h>
#define SIZE 32
int isQuit(char str[]);
void isPalindrome(char str[]);
int main (){
int cont = 0;
char str[SIZE];
fflush(stdin);
printf("please enter a word:\n");
scanf("%s\n", str);
printf("%s\n", str);
while(cont == 0)
{
scanf("%s\n", str);
printf("%s\n", str);
cont = isQuit(str);
isPalindrome(str);
}
return 0;
}
You most likely are suffering from line buffering in your terminal. Until you write a newline character, any characters written are not displayed.
Try adding a newline when displaying your input:
printf("%s\n", str);
The same goes for any other printf calls you do that you want to ensure are displayed.
By the way, your null-termination test is incorrect. The escape character is \, not /. Change your loop to:
while (str[h] != '\0')
Or simply:
while (str[h])
There are a few things wrong with your code here:
while(isQuit(str) == 0)
{
isPalindrome(str);
return 0 ;
}
Since you have the return keyword in your loop body (unconditionally), the loop will execute at most one time.
Also, neither isQuit nor isPalindrome take input from the user. This means that even if you were to fix the loop by removing the return statement, it still wouldn't be right; you'd have an infinite loop of isQuit and isPalindrome being passed the same str that the user got asked for on line 15.
What you have to do is change your while loop to continually poll the user for input and act upon it, in addition to the issues pointed out in #paddy's answer.

How do I get the user to input a word for string comparison?

I'm running a while loop so the user can constantly enter expressions, until they indicate they want to quit the program. I'm using strcmp() to compare two strings so as soon as they enter quit the program will stop. But the program keeps going, any Ideas?
#include <stdio.h>
#include <string.h>
int main()
{
int min12=0;
char opper;
int x=0;
int min13;
char *Repeatprog="cont";
char *Repeatprog1="quit";
while (strcmp(Repeatprog,Repeatprog1))
{
printf("enter the integer number \n");
scanf( "%d %c %d", &min12, &opper, &min13);
printf("%d %c %d\n", min12, opper, min13);
printf("Type the word quit to end program\n");
scanf("%s", Repeatprog);
}
printf("Good Bye");
return 0;
}
Remember always that an Array is a Pointer to the first object of the array.
And secondly, in your call to scanf() you only read a character. Not a whole string (represented by %s in C)
So in conclusion, your call to scanf() shouldn't have a pointer and should have a string instead of a character.
scanf("%s", Repeatprog);
or simply
gets (Repeatprog);
EDIT :
As the commenter #EOF said, gets() is not a good idea since it can lead to Undefined Behaviour. That's because the program can read more characters than it should have and lead to overflow, thus it isn't secure.
So I recommend using char *fgets(char *str, int n, FILE *stream)
Note:
Also, your code is using string literals. So if you make any attempt to change the content of the char pointer then it will lead to Undefined Behaviour.
For this note, please thank the guys below me [comments]. I made a huge mistake and I'm sorry.

Printf inserts % at the end of the line

I'm writing a basic program to learn how to use basic input/output in C, and it works just fine. The only problem I have is when it prints, there is a "%" at the end of the string on the terminal. Here's my code:
#include <stdio.h>
int main(int argc, char **argv) {
char name[32];
printf("Enter your name: ");
scanf("%s", name);
printf("Hello, %s", name);
return 0;
}
When I run the program, the output is Hello, Andrew%
Any help?
There's nothing in your code that should explain this behavior. However, it seems likely that if you are running this from a shell, that may be your shell prompt.
Add a newline to your output:
printf("Hello, %s\n", name);
This should cause the prompt to print on the next line as you probably expected.
The stdout stream is line buffered. What this means is the output does not appear on the console until a newline is output or the buffer is full. This may be a cause why you are seeing a % on the screen. '\n' causes printf to print the output immediately on the screen.
Note that if the input string is larger than 31 characters, then scanf will overrun the buffer name invoking undefined behaviour. This may crash the program due to segfault. You should safeguard against it by providing the maximum field width which should be 1 less than the array length to accommodate for the terminating null byte added by scanf.
#include <stdio.h>
// if your not using command line argument, use the below
// signature of main
int main(void) {
char name[32];
printf("Enter your name: \n"); // add a newline to output
scanf("%31s", name); // -1 for the terminating null byte
printf("Hello, %s\n", name); // add a newline to output
return 0;
}
As you have not output a new line - that is your shell prompt character being shown after the specified output. Try printf("Hello, %s\n", name);
Run this command line PROMPT_EOL_MARK='' into your zsh shell, that should be enough to fix it.

Scanf not accepting second char string

I have a binary search function that will search for a word in an array, but before I can search the array I need to know what word to search for. I have written the code to ask the user for input, but the program prints out the request for input but doesn't accept anything from the user. I was thinking it was a buffer issue, as I have an initial scanf in the program that loads all the character strings from an external file and places them in an array. I have tried using fflush after my initial scanf, and I tried rewriting the second one with gets, as pointed out in previous threads. Perhaps I am not implementing it correctly. Here's what I have so far, any tips as to why the second scanf isn't working is appreciated.
#include "set.h"
#include "sortAndSearch.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(){
char names[320][30];
char str[30];
int i, j;
char *key;
int numOfWords;
char userWord[30];
Set set1, set2, set3;
//scan each char string into array names
for(i=0; scanf("%s", str) != EOF; i++){
strcpy(names[i], str);
}
//set number of words in file
numOfWords = i;
//sort names array
//bubbleSort(names, numOfWords);
//print out names, sorted
//for(i=0; i<numOfWords; i++){
// printf("%s\n", names[i]);
//}
printf("What word would you like to search for? ");
scanf("%s", userWord);
//addName2Set(set1, userWord);
return 0;
}
Your second scanf doesn't work because your first scanf never terminates. scanf won't return EOF unless the input stream is closed - that would be that the console closes.
Since scanf returns the number of characters read you should instead make your loop condition scanf(%s, str) != 0. That will make the loop end as soon as the user hits enter without entering anything.
Your initial scanf() in a loop read everything up to EOF, so there's nothing left for the 'What word would you like to search for?' scanf() to read.
One way around this problem is to read the initial names from a file (fopen(), fscanf(), fclose() — and the file name might be an argument to the program, or a fixed name).
Another way you could try is clearerr(stdin); before the 'What word' scanf(). That (clearerr()) unsets the EOF bit and allows scanf() to try again. It may work if the input of the program is the terminal; it won't help if the input of the program is coming from a file.
int main(int argc, char **argv)
{
char names[320][30];
char str[30];
int i, j;
char *key;
int numOfWords;
char userWord[30];
Set set1, set2, set3;
FILE *fp;
if (argc != 2)
{
fprintf(stderr, "Usage: %s word-file\n", argv[0]);
exit(1);
}
if ((fp = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Usage: %s word-file\n", argv[0]);
exit(1);
}
//scan each char string into array names
for (i = 0; i < 320 && fscanf(fp, "%29s", str) != EOF; i++)
{
strcpy(names[i], str);
}
fclose(fp);
//set number of words in file
numOfWords = i;
This insists that you use ./a.out example.dat (instead of ./a.out < example.dat). It will then work more or less as you want it to. Of course, the code for reading the file should be in a function that is passed the file name, the array, and the array size. The 320 in the loop is overflow protection and should be an enumeration enum { MAX_WORDS = 320 }; that's used both in the array declaration and the loop. The 29 is overflow protection; it is hard to parameterize that, but it is one less than the second dimension of the array.
Your question and code seemed awfully misaligned at first glance...
scanf() is the wrong function for reading from your file, you want fscanf(), or if the file is formatted such that each word is on its own line fgets() works too (newline stops reading of each string). Likewise, you can use gets() instead of scanf() to read user input if the input is just a string followed by return(newline).
Everything you need to know about stdio.h

C string concatenation

I am trying to input 2 strings in C, and output a 3rd string which the concatenation of string 1 and 2.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*/
int main(int argc, char** argv) {
char stringarray1 [30];
char stringarray2 [30];
char stringarray3 [30];
int length;
printf("Please enter some text less than 30 characters long\n");
scanf("%[a-z, ]", &stringarray1);
printf("Please enter some text less than 30 characters long\n");
scanf("%[a-z, ]", &stringarray2);
strcat(stringarray1, stringarray2);
//length = strlen(stringarray);
printf("The combined string is %s\n", stringarray1);
return (EXIT_SUCCESS);
}
It allows me to input the first string, but then prints the seond and third printf statement, without allowing me to enter the second string.
How can i enter the second string without it exiting? Why does it exit?
Have a look at the documentation of scanf: Your format string "%[a-z, ]" does not what you seem to think what it does. Just use "%s" for strings instead. (It's without any character checks).
You should not put the & for your arrays that are already pointers.
scanf("%[a-z, ]", stringarray2);
At a guess, I'd say you need a \n inside your scanf specification strings. You should probably also be asking for %s instead of %[a-z, ]. The way you have it a single character would match, then when the second scanf is hit, the next character would match.
Also there are some safety issues. You should probably be checking to make sure both strings together aren't larger than 30 chars. As Benoit pointed out, arrays in C also double as pointers to the first character, so you don't use the address-of operator (&) on them when passing them to the C IO routines. That would give the routine the address of your array pointer itself, which the IO routine would then merrily wipe out with character data. Not good!
You know the difference between an chararray a stringarray? I think not. Also you must allocate enough space for you result-string, like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
*
*/
int main(int argc, char** argv) {
char chararray1 [31];
char chararray2 [16];
char chararray3 [30];
int length;
printf("Please enter some text less than 15 characters long\n");
scanf("%15[a-z, ]", stringarray1);
printf("Please enter some text less than 15 characters long\n");
scanf("%15[a-z, ]", stringarray2);
strcat(stringarray1, stringarray2);
//length = strlen(stringarray);
printf("The combined string is %s\n", stringarray1);
return (EXIT_SUCCESS);
}
I would recommend using fgets instead of scanf, that you can specify a max length (buffer target size - 1) and avoid surprises.
also the target buffer should be twice the size of your input buffers otherwise you risk a memory overwrite

Resources