string modification taking input using get - c

I am trying to modify value of one string using other .
#include <stdio.h>
#include <string.h>
int main(void) {
char ch[10],s[3];
int c;
fgets(ch,10,stdin);
fgets(s,2,stdin);
c=(int)s[1];
ch[3]+=c;//s[1];
printf("%c\n",s[1]);
printf("%s",ch);
return 0;
}
Output is blank for s[1] and ch remains unchanged . However the program works fine if i remove the second gets and use a constant in place of c.
I would like to know the my error as well as the best simple approach for string manipulation .
EDIT : changed s[2] to s[3] , still same result

If the second fgets() read something (1 character), a terminating null character will be written to s[1].
Bits in terminating null character are all zero, and it means that the value of s[1] will become 0.
Adding zero means almost nothing.

You are running into a combination of issues. The first being if you are reading fgets(s,2,stdin); you get a maximum of 1 character in s plus the nul-terminating character. If you then take c=(int)s[1]; you are reading the second character of s into c. The second character of s will always be either '\n' (0xa hex, 10 decimal) if 1 character is entered or 0 (the nul-terminating char).
You run into your next problem with ch[3]+=c;. The result of which must fall within the printable range of characters. (see: asciitable.com ). That means if ch contains AAAA, the first character of s must have an ASCII value of 61 or less to remain in the printable character range.
Take the following example:
#include <stdio.h>
int main (void) {
char ch[10] = "",
s[3] = "";
int c = 0;
printf (" first input : ");
fgets (ch, 10, stdin);
printf (" second input: ");
fgets (s, 3, stdin);
printf ("\n you entered:\n first : %s second: %s\n", ch, s);
c = s[0];
ch[3] += c;
printf(" s[1] : %c\n",s[0]);
printf(" ch : %s\n",ch);
return 0;
}
Example Use
$ /bin/fgetsbasic
first input : HAHA
second input: !
you entered:
first : HAHA
second: !
s[1] : !
ch : HAHb
Anything with an ASCII value greater than 61 will cause you to fill the 4th character of ch with a non-printable value. (this changes depending on what the 4th char in ch originally is)

Related

Output didn't include all of the characters

I was trying to input a string of characters and only output the last and the first character respectively. Below is the code I'm using.
#include<stdio.h>
int main(){
for(int i=0;i<3;i++){
int n; // length of the string
char string[101];
scanf("%d %s", &n, &string);
fflush(stdin); // sometimes I also use getchar();
printf("%c%c", string[n+1], string[0]);
}
printf("\n");
return 0;
}
I'm using for loop because i wanted to input the string 3 times, but when I ran the code the input isn't what I expected. If I input e.g.
5 abcde
output
a //there's space before the a
can you help me tell where I've gone wrong?
input:
5 abcde
6 qwerty
3 ijk
excpeted output:
ea
yq
ki
Few problems in your code:
In this statement
scanf("%d %s", &n, &string);
you don't need to give & operator with string. An array name, when used in an expression, converts to pointer to first element (there are few exceptions to this rule). Also, the size of string array is 101 characters but if you provide input more than 101 characters, the scanf() end up accessing string array beyond its size. You should restrict the scanf() to not to read more than 100 characters in string array when input size is more than that. (keep the remain one character space is for null terminating character that scanf() adds). For this, you can provide width modifier in the format specifier - %100s.
You are not validating the string length input against the input string from user. What happen, if the input string length is greater than or less than the actual length of input string!
fflush(stdin) is undefined behaviour because, as per standard, fflush can only be used with output streams.
I was trying to input a string of characters and only output the last and the first character respectively.
For this, you don't need to take the length of the string as input from user. Use standard library function - strlen(). This will also prevent your program from the problems that can occur due to erroneous length input from user, if that is not validated properly.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main (void) {
for (int i = 0; i < 3 ; i++) {
char string[101];
printf ("Enter string:\n");
scanf("%100s", string);
printf("Last character: %c, First character: %c\n", string[strlen(string) - 1], string[0]);
int c;
/*discard the extra characters, if any*/
/*For e.g. if user input is very long this will discard the input beyond 100 characters */
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
}
return 0;
}
Note that, scanf(%<width>s, ......) reads up to width or until the first whitespace character, whichever appears first. If you want to include the spaces in input, you can use the appropriate conversion specifier in scanf() or a better alternative is to use fgets() for input from user.
Line 11: string[n+1] -> string[n-1]

to print each character of a word in c program

I am having a c program which print letter by letter of the word. I referred this program from this link
https://www.tutorialgateway.org/c-program-to-print-characters-in-a-string/. If I run this program in online c compiler this gives the exact result, but not working in turbo c++
#include <stdio.h>
int main()
{
char str[100];
printf("\n Please Enter any String : ");
scanf("%s", str);
for(int i = 0; str[i] != '\0'; i++)
{
printf("The Character at %d Index Position = %c \n", i, str[i]);
}
return 0;
}
This program doesn't through any error, but I don't know why this program doesn't print the result.
Try fgets(str, 100, stdin) instead of scanf(). This is the normal way to read a line into a buffer. When I used scanf() I only got part of the output because it will stop reading a string at a space.
IDK what is your output, but here is mine:
Please Enter any String : Hell got loose
The Character at 0 Index Position = H
The Character at 1 Index Position = e
The Character at 2 Index Position = l
The Character at 3 Index Position = l
This is normal, due to this:
Matches a sequence of non-white-space characters; the next pointer must be a pointer to character array that is long enough to hold the input sequence and the terminating null character ('\0'), which is added automatically. The input string stops at white space or at the maximum field width, whichever occurs first.
this is taken from scanf.
EDIT:
Just for the fun, you can do this using scanf
scanf("%[^\n]",str);
this will replace \n newline with '\0'.
NOTE: #Joshua's answer is safer, if you want to know why just google why I shouldn't use scanf()

How to check if user input numbers instead of string(array of char) in C

So, I got this assignment as a student that ask me to create a simple program using C.
This program input only allow you to input only characters A-Z, a-z, and (space).
and the length of the string should be no less than 1 character and no more than 100 characters.
So, I come with the conclusion that I should use if function to validate if the user input the allowed character.
#include <stdio.h>
#include <ctype.h>
int main()
{
char name[100];
scanf("%s",&name);
fflush(stdin);
if (isdigit(name))
^^^^
{
printf("Wrong answers");
getchar();
}
else
....
It was supposed to print "wrong answers" if you input numbers in there, but this program won't run.. It keeps saying :
error C2664: 'isdigit' : cannot convert parameter 1 from 'char [100]' to 'int'
I don't know what this error means.. Is there something I miss? Or am I using the wrong function?
I have also tried
if (((name>='A')&&(name<='Z'))||((name>='a')&&(name<='z')||)((name==' ')))
{
//this print what i want
}
else
{
printf("wrong answers");//this print "wrong answer"
}
but it always print "wrong answers" no matter I input the correct input or the wrong input.
Your help is highly appreciated.
Thank you.
*ps : I am a beginner at programming.
isdigit() takes an int as argument, not a char*:
int isdigit(int c);
You have to use a loop over the string and check each character in it.
Having said that, to achieve:
this program input only allow you to input only characters 'A'-'Z', 'a'-'z', and ' '(space)
you are better off using isalpha().
Try this out:
#include <stdio.h>
#include <ctype.h>
int main()
{
int i = 0;
char name[101], temp;
// take input one character at a time
while(scanf("%c", &temp)){
// stop when newline or carriage return
if(temp == '\n' || temp == '\0' || !isalpha(temp) ){
break;
}
// save character in array
name[i] = temp;
// move to the next position of the array
i++;
}
printf( "%s", temp );
return 0;
}
The problem you're seeing is that you're passing isdigit the wrong type of value - it expects an int, but you're passing it an array of char. You would have to loop over each and every character in your string to check if it's a digit or not.
But that is ultimately not what you're after as you're looking to confirm that the string contains letters or spaces - there are lots of characters that could be entered that aren't classed as digits that would be accepted incorrectly.
What would be the easiest solution for you, is to use the function strspn. It takes a string and returns the length of how many characters match the second parameter. If that length is the same length as your string, you know that it only contains valid characters.
size_t valid;
valid=strspn(name, "abcdefg(fill in with other valid characters)");
if(valid==strlen(name))
{
// Valid name
}
else
{
// Not valid
}
If you need to expand the accepted characters, it's just a simple case of adding them to the 2nd parameter.
OP's code fails as isdigit() test is a single character is a digit (0-9). It does not test a string.
int isdigit(int c);
The isdigit function tests for any decimal-digit character.
In all cases the argument is an int, the value of which shall be
representable as an unsigned char or shall equal the value of the macro EOF.
OP's buffer is too small to save 100 characters read from the user. At least 1 more needed to detect if too many were read and 1 more for a null character to mark the end of a string.
fflush(stdin); has its problems too.
scanf("%s",&name); does not save white-space. The parameter should have been name too. (no &)
Read a line of user input with fgets() which saves the result as a string.
Test if the input meets the criteria.
Read
#define N 100
// No need to be stingy on buffer size reading user input. Suggest 2x
// We need +1 for extra character detection, \n and \0
char buf[2*N + 1 + 1];
fgets(buf, sizeof buf, stdin);
// lop off potential \n
size_t length = strlen(buf);
if (length > 0 && buf[length-1] == '\n') {
buf[--length] = '\0';
}
Test
only characters 'A'-'Z', 'a'-'z', and ' '(space).
for (size_t i = 0; i<length; i++) {
if (!isalpha((unsigned char)buf[i]) && buf[i] != ' ') {
puts("Invalid chracter");
break;
}
}
length of the string should be no less than 1 character and no more than 100 characters.
if (length < 1 || length > 100) {
puts("Input wrong length");
}
Others approaches can be used to disqualify very long inputs. IMO, very long inputs represent an attack and should be handled differently than a simple line that was a bit too long.
if (length < 1 || length > 100) {
if (length + 2 >= sizeof buf) {
puts("Input way too long");
exit (EXIT_FAILURE);
}
puts("Input wrong length");
}
name must have one extra space for the \0 (NUL) character.
So to store 100 characters, its size should be at least 101.
char name[101];
You could first use
fgets(name, sizeof(name), stdin);
to read into name character array.
Note that fgets() will read in the trailing newline (\n) as well which need be removed like
name[strlen(name)-1]='\0';
Then use sscanf(). Like
size_t l=strlen(name);
sscanf(name, "%100[A-Za-z ]", name);
if(strlen(name)!=l)
{
printf("\nInvalid input.");
}
Note the space after the A-Za-z.
The 100 in the %100[A-Za-z] denotes reading at most 100 characters into name. The [A-Za-z ] will make the sscanf() stop reading if a non-alphabetic character which is not a space is encountered.
First read into name. Then store its length in l. Now read everything till a non-alphabet other than a space occurs in name to name itself (thereby modifying name).
Now compare the length of this new string with l. If they are the same. The input is valid as per your need.
You could also use scanf() instead of fgets() like
scanf("%100[^\n]", name);
which instructs to read every character till a \n into name. If this is used, no \n will added at the end of name unlike the case with fgets().
Now I would like to point out some mistakes in your code.
scanf("%s",&name);
will lead to errors. Correct one is
scanf("%s",name);
as the second argument here must be an address and since an array name in C decays into its base address, just name would do instead of &name.
As others have pointed out, using fflush() on stdin is undefined and must be avoided.
If you are trying to clear the input buffer till the next newline (\n), you could do
int ch;
while((ch=getchar())!='\n');// && ch!=EOF)
The argument of isdigit() must be a char and not a character array (type char [100] if size is 100).
And if is a statement and not a function.

Why does the presence of `n` in the input sentence before `\n` give wrong output?

I want to input a sentence (containing any possible characters) and print it. But there is a catch. If there is a \n in the sentence then only the part of the sentence before \n should be printed out (i.e. \n should signify the end of the inputted sentence). I wrote a code for this situation :
#include <stdio.h>
main()
{
char ch[100];
printf("Enter a sentence");
scanf("%99[^\\n]",&ch);
printf("%s",ch);
}
This code seems to work fine but it fails in a certain situation.
If there is the character n anywhere in the sentence before \n then it prints only the first word of the sentence! Why does this happen? How can I fix this bug?
This case works fine:
But in this case it fails:
Detail from comments:
Q: Do you want to to stop at a newline, or at a backslash followed by n?
A: slash followed by n
The [] conversion specifier of scanf() works by defining an accepted (or, with ^, rejected) set of characters. So %[^\\n] will stop scanning at the first \ or the first n -> You can't solve your problem with scanf().
You should just read a line of input with fgets() and search for an occurence of "\\n" with strstr().
Side note: there's an error in your program:
char ch[100];
scanf("%99[^\\n]",&ch);
ch evaluates as a pointer to the first element of the array (so, would be fine as parameter for scanf()), while &ch evaluates to a pointer to the array, which is not what scanf() expects.
(the difference is in the type, the address will be the same)
OP's calcification negated the first part of this answer.
OP has not formed the desired scan set for the "%[...]" specifier.
"%99[^\\n]" accepts any character except '\\' and 'n'.
Certainly OP wants "%99[^\n]". \\ changed to \ to accept any character except '\n'.
Yet I would like to take the goal up a bit. This part is only for pedantic code.
input a sentence (containing any possible characters)
How would code handle this if the null character '\0' was included in that "any possible character"?
Note that inputting a null character is not often easy from a keyboard.
Interestingly "%99[^\n]" will scan up to 99 characters (except a '\n') including the null character. Yet the below code prints ch as it it were a string and not a general array of characters.
#include <stdio.h>
int main(void) {
char ch[100];
printf("Enter a sentence\n");
if (scanf("%99[^\n]", ch) != 1) {
ch[0] = '\0'; // Handle a line of only `'\n``, EOF, or error
}
printf("%s",ch);
}
To accomplish this esoteric goal with scanf() (not the best tool in the shed), record the length of the scan and then print the array.
int main(void) {
char ch[100];
int n;
printf("Enter a sentence\n");
if (scanf("%99[^\n]%n", ch, &n) != 1) {
n = 0; // If scanning stopped right away, set length `n` to 0
}
// Write as an array
fwrite(ch, sizeof ch[0], n, stdout);
}

Parsing number into digits with scanf()

I want to type in a number that is 10 digits long, then put the digits into an array. But for some reason, I get this random 2-digit numbers that seem to have nothing to do with my input (??).
char number[10]; //number containing 10 digits
scanf("%s",number); //store digits of number
printf("%d\n",number[0]); //print the 1st digit in the number
printf("%d\n",number[1]); //print the 2nd digit in the number
Here is what I got:
Input:
1234567890
Output:
49
50
Actually, 49 should be 1, and 50 should be 2.
You are getting ASCII value of characters 1 and 2. Use %c specifier to print the digits.
printf("%c\n",number[0]);
Warning! Your code may invoke undefined behaviour!
But we'll talk about it later. Let us address your actual question first.
Here is a step by step explanation of what is going on. The first thing you need to know is that every character literal in C is actually an integer for the compiler.
Try this code.
#include <stdio.h>
int main()
{
printf("%d\n", sizeof '1');
return 0;
}
The output is:
4
This shows that the character literal '1' is represented as 4 byte integer by the compiler. Now, let us see what this 4 byte integer for '1' is using the next code here.
#include <stdio.h>
int main()
{
int a = '1';
printf("a when intepreted as int : %d\n", a);
printf("a when intepreted as char: %c\n", a);
return 0;
}
Compile it and run it. You'll see this output.
a when intepreted as int : 49
a when intepreted as char: 1
What do we learn?
The character '1' is represented as the integer 49 on my system. This is so for your system too. That's because in my system as well as yours, the compiler is using ASCII codes for the integers where '1' is 49, '2' is 50, 'A' is 65, 'B' is 66, and so on. Note that the mapping of the characters to these codes could be different for another system. You should never rely on these integer codes to identify the characters.
So when I try to print this value as integer (using %d as the format specifier), well what gets printed is the integer value of '1' which is 49. However, if we print this value as a character (using %c as the format specifier), what gets printed is the character whose integer code is 49. In other words, 1 gets printed.
Now try this code.
#include <stdio.h>
int main()
{
char s[] = "ABC123";
int i;
printf("char %%d %%c\n");
printf("---- -- --\n");
for (i = 0; i < 6; i++) {
printf("s[%d] %d %c\n", i, s[i], s[i]);
}
return 0;
}
Now you should see this output.
char %d %c
---- -- --
s[0] 65 A
s[1] 66 B
s[2] 67 C
s[3] 49 1
s[4] 50 2
s[5] 51 3
Does it make sense now? You need to use the %c format specifier when you want to print the character. You should use %d only when you want to see the integer code that represents that character.
Finally, let us come back to your code. This is how you fix it.
#include <stdio.h>
int main()
{
char number[10];
scanf("%9[^\n]", number);
printf("%c\n", number[0]);
printf("%c\n", number[1]);
return 0;
}
There are two things to note.
I have used %c as the format specifier to print the character representation of the digits read.
I have altered the format specifier for scanf to accept at most 9 characters only where the characters are not newline characters. This is to make sure that a user cannot crash your program by inputting a string that is far longer than 9 characters. Why 9 instead of 10?. Because we need to leave one cell of the array empty for the null-terminator. A longer input would overwrite memory locations beyond the allocated 10 bytes for the number array. Such buffer overruns lead to code that invoke undefined behaviour which could either cause a crash or kill your cat.
printf("%c\n",number[0]); //print the 1st digit in the number
printf("%c\n",number[1]);
should do the job for you, what you see are ascii values.
your number array is an array of char, and so every element of it is a char.
when you type:
printf("%d\n",number[0]);
you printing the chars as integers, and so you get the ASCII code for each char.
change your statement to printf("%c\n",number[0]); to print chars as chars not as ints
Warning! Your code invokes undefined behaviour!
char number[10]; // Can only store 9 digits and nul character
scanf("%s",number); // Inputting 1234567890 (11 chars) will overflow the array!
Use fgets instead:
#define MAX_LEN 10
char number[MAX_LEN];
if(fgets(number, MAX_LEN, stdin)) {
// all went ok
}
Once you have fixed this, you can fix the printing problem. You are printing the character code (number), and not the actual character. Use different type specifier:
printf("%c\n",number[0]);

Resources