program to write initials of string - c

I Am trying to make a program to make the user to enter his first name then middle then last name each followed by space like this example:
sample input: mark brown ashraf
sample output: m b a
and when i debug i got "access violation error"
#include<stdio.h>
#include<conio.h>
#include<string.h>
int main(void)
{
char name[100];
int i=0;
printf("Enter the name :");
gets(name);
while (name[i]!='\0')
{
if (name[i]==' ')
{
i++;
printf("%c",name[i+1]);
}
i++;
}
getch();
}
"now it dont give me the first initial but printed the rest of initials "

The access violation happens, because you use the wrong format specifier in your printf call.
printf("%s", name[i+1]);
should be
printf("%c", name[i+1]);
or maybe even more directly:
putchar(name[i+1]);
The violation occurs, because %s expects a pointer, which the printing function then dereferences. The char value you pass isn't a valid memory address.
Please switch on compiler warnings. They can usually tell you that your format string doesn't match the arguments.
Edit Besides the access violation, there are more problems in your program:
You increment i twice after a space, so that you actually print the second letter of each word. (Or even a space if your input is "Taylor C Huckleberry").
You don't catch the first word, unless your input begins with a space character.
You could end up printing the '\0' character when your input has trailing spaces.
You could print additional spaces if your input has subsequent spaces.
There are also some formal programming errors:
main is supposed to return an int, but your code never does.
You use the obsolete gets, which has been superseded with the more secure fgets. (Unformtunately, fgetskeeps a trailing newline, but it shouldn't matter for your code.)
In my opinion, a better approach is to keep track of the previously read character and to print the initial only if the previous char was a space and the current one is a letter. The header <ctype.h> provides the handy functions isspace and isalpha to check this. The previously read character starts off as a space character, so that you catch the first word:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
char name[100];
char prev = ' '; /* pretend there's a space before the string */
int n = 0; /* number of initials printed */
int i = 0;
printf("Enter the name: ");
fgets(name, sizeof(name), stdin);
while (name[i]!='\0') {
if (isalpha(name[i]) && isspace(prev)) {
if (n++) putchar(' ');
putchar(name[i]);
}
prev = name[i];
i++;
}
putchar('\n');
return 0;
}

while (name[i]!='\0')
{
if (name[i]==' ')
{
i++;
printf("%s",name[i+1]);
}
i++;
}
SInce you are incrementing i twice inside the loop there is a possibility that you might have access array out of bound. This is a potential error.
gets() is no more a standard and you should use fgets() instead which will handle buffer overflow.

Related

Print a middle character of a string

I must write a program in C that can print the middle letter of the string you entered. Spaces () are also calculated, and the number of characters must be odd.
Ex. Input
Hi sussie
--> 9 characters, including space
The output should be s.
I have tried this:
#include <stdio.h>
#include<string.h>
char x[100];
int main(void)
{
printf("Hello World\n");
scanf("%c\n",&x);
long int i = (strlen(x)-1)/2;
printf("the middle letter of the word is %c\n",x[i]);
return 0;
}
and the output always shows the first letter of the word I have entered.
You're only reading the first character from stdin (and incorrectly; you shouldn't be using &).
If you must use scanf, you should use this format:
scanf("%99[^\n]", x);
This is safe and doesn't read past the buffer.
Note that %s wouldn't work here. %s causes scanf to interpret whitespace as the end of the string.
A much better, safer, and easier solution would be to use fgets instead of scanf; fgets is safer and it doesn't require you to change a format string when you change the size of your array:
fgets(x, sizeof(x)-1, stdin);
This eliminates any possible issues with whitespace or buffer overflow.
int main()
{
char arr[1024];
char a;
int i,counter=0;
printf("enter string :: ");
fgets(arr,sizeof(arr),stdin);
for(i=0;i<strlen(arr);i++)
counter++;
for(i=0;i<strlen(arr);i++)
{
if(i==(counter/2))
printf("%c\n",arr[i]);
}
return 0;
}

Can't find space in string and specified char , even by simple method

I am using this method to find a space or specified word in string.
but this method doesn't works. I've checked the flow many times.
#include <stdio.h>
int main()
{
char text[50], find;
int i = 0, sp = 0;
printf("Enter text: \n");
scanf("%s", text);
printf("Enter a char to find:\n");
scanf("%c", &find);
while ( text[i] != '\0') // to receive a value untill enter is pressed.
{
if (text[i] == find) // count if text[i] is the specified value.
{ sp++; }
i++;
}
printf("%d", sp); // prints 0 always. how to fix this.
}
The find in your code is always assigned with \n or the new line character that you enter at the end of scanning your string text .Try giving a space in scanf statement of find :
scanf(" %c",&find)
Why to give a space?
By giving a space,the compiler omits the '\n' character from the previous scanf
Note: scanf("%s",string) ends scanning when it encounters white space i.e, '\n' or '\0' or '\t' but to account for spaces, try
using this scanf("%[^\n]s",string")
You cannot use scanf() to read a string of characters with space. As soon as the space is encountered, scanf() exits.
Use fgets() instead.
And as for finding a word in the string, to compare strings use strcmp().
SIDE NOTE:
1) Check the return values of scanf()
2) Use the standard definition of main()
int main(void) //if no command line arguments.
I found a solution for that:
scanf("%[^\n]", fullName);
works fine. and receives whole line

Input a password from the user and check if it has a char, alphabet and digit

My doubt is that, the program works fine if I enter a password that fills the array. However if I enter a password such as "apple25", I think it counts the blank spaces in the array as characters and even declares "apple25" as a valid password.
How do I prevent this from happening? Does it count the string terminator also as a char? Because even "AAPPLLEE2" comes as a valid password.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
int main()
{
char arr[10];
printf("Enter a password. \n");
scanf("%s",arr );
// printf(arr);
char ch;
int i;
int alp=0, dig=0, c=0;
for (i=0; i<10; i++)
{
ch=arr[i];
if(isalpha(ch))
{
alp++;
// printf(" alpha is %d \n",alp);
}
else if(isdigit(ch))
{
dig++;
// printf("digit is %d \n",dig);
}
else
{
c++;
// printf("charectores are %d \n",c);
}
}
if(alp>=1&&dig>=1&&c>=1)
{
printf("Valid Password");
}
else{
printf("Invalid Password");
}
return 0;
}
Point 1. Always initialize your automatic local variables. Saves you from accidentally accessing un-initialized value.
char arr[10] = {0};
Point 2. Always limit your input length. Saves you from running into undefined behavior by overrunning the allocated memory by longer-than-expected input.
scanf("%9s",arr );
Point 3. Use strlen() to loop over only the valid part of input.
That's because your loop runs over the entire, not just upto the characters you read.
Instead do,
size_t len = strlen(arr);
for (i=0; i<len; i++) {
...
}
You may also want to use fgets() to avoid buffer overrun. If you enter more than 10 characters, you'll overflow arr, which is undefined behaviour.
Instead of
scanf("%s",arr );
do
fgets(arr, sizeof arr, stdin);
char *p = strchr(arr, '\n');
if(p) *p = 0; //trim the trailing newline, if present
I think it counts the blank spaces in the array as charecters and even declares "apple25" as a valid password.
Your assumption is almost right. Your program does count characters after the end of user input, but they are not necessarily blanks.
You get this effect with "AAPPLLEE2" because your code examines ten characters of a nine-character string. The tenth character is null terminator, which is neither a digit nor a letter.
You need to use the actual length for the limit of the loop, rather than hard-coding the limit of ten.
You should also fix the potential buffer overrun:
char arr[11]; // <<== Add one more character for '\0'
printf("Enter a password. \n");
scanf("%10s",arr ); // <<== Tell scanf how big is your buffer
There are several issues here:
Try entering a password with a size of 10 or longer. You'd overflow arr.
You don't stop at the terminating NULL character (value 0). In fact, you count the terminating NULL as "character" and increase c when you come across it.
Any garbage afterward is also processed.

C Program infinite loop unexpectedly when used scanf

I checked here and there and wasted around 3 hours checking for a solution. My program just infinite loop itself. Here is my C program:
#include <stdio.h>
#include <string.h>
int main (void)
{
int attempts = 0;
char password[10];
do
{
printf("Enter your password:\n");
scanf("%[^\n]s", password);
printf("\n");
attempts++;
} while (strcmp(password, "awesome 123 ok"));
printf("You entered a correct password in %d attempts!", attempts);
return 0;
}
I tried scanf("%[A-Za-z0-9 ]s", password)"so it can take all characters and numbers including space as an input but it just loop. And I also tried using getchar() but it asks for password again and again even if I enter the correct one. Any help will be appreciated.
Size of awesome 123 ok is 15 including \0. But you are allocating memory for 10 bytes. It causes undefined behavior.
When you are using %[^\n] format specifier no need to use s with that, It will automatically scan the spaces also.
Try the following changes-
int main (void)
{
int attempts = 0;
char password[20]; // Fix 1
do
{
printf("Enter your password:\n");
scanf("%[^\n]", password); // Fix 2
printf("\n");
attempts++;
} while (strcmp(password, "awesome 123 ok"));
printf("You entered a correct password in %d attempts!", attempts);
return 0;
}
You declare char password[10]; but you compare it with awesome 123 ok which has more characters.
From this scanf (and family) reference:
All conversion specifiers other than [, c, and n consume and discard all leading whitespace characters before attempting to parse the input.
That means that the trailing newline (a whitespace character) will be included in the next call to scanf in the loop.
The solution is simple: Tell scanf to read and discard leading whitespace:
scanf(" %[^\n]", password);
/* ^ */
/* | */
/* Note leading space */
Also note that I removed the trailing s in the format, because that tells scanf to expect a literal s in the input. The "%[" format ends with the closing ']'.
You also might want to limit the number of characters read so you don't overflow the buffer you read into:
scanf(" %9[^\n]", password);
Note that the above format set the maximum field width as nine characters, because the buffer needs to include the terminating '\0' character as well. Modify this number if you increase the buffer size, but remember that it should be (at most) one less than the buffer size.
Change the dec password[10] to password[20]
I would use fgets because it is a safer way than gets or scanf:
#include <stdio.h>
#include <string.h>
int main (void) {
int attempts = 0;
char password[20];
do {
printf("Enter your password:\n");
fgets(password, sizeof(password), stdin);
password[strlen(password) - 1] = '\0';
printf("\n");
attempts++;
} while (strcmp(password, "awesome 123 ok"));
printf("You entered a correct password in %d attempts!", attempts);
return 0;
}
Now, this will only work if you increase the size of password[] as I did in my example. When not using fgets it might still work in a bad way because you are comparing a buffer overflow.
The issue is that password is too narrow. Because of this, the program routinely writes past the end of the array, resulting in undefined behaviour.
You can fix this by making password wider. However, your program will still be open to stack smashing: an attacker can potentially execute arbitrary code by entering a long carefully crafted password string.
To fix that, you need to change the scanf() format specifier to limit how many characters it can store in password.
The following changes will fix both:
char password[32]; /* more space: 31 characters + NUL */
do {
...
scanf("%31[^\n]%*c", password); /* format specifier */
The latter will make sure you're never reading more than 31 characters into password; it also consumes the newline without storing it.
Add getchar() to consume the \n character. Find the modified code in below.
int main (void)
{
int attempts = 0;
char password[10];
do
{
printf("Enter your password:\n");
scanf("%[^\n]s", password);
getchar (); // Fix1
printf("\n");
attempts++;
} while (strcmp(password, "awesome 123 ok"));
printf("You entered a correct password in %d attempts!", attempts);
return 0;
}
The array password is not used properly in your code. So change the logic for it. User can enter N numbers of character. So restrict the user input to limited character or use dynamic memory allocation

Reading string from input with space character? [duplicate]

This question already has answers here:
How do you allow spaces to be entered using scanf?
(11 answers)
Closed 4 years ago.
I'm using Ubuntu and I'm also using Geany and CodeBlock as my IDE.
What I'm trying to do is reading a string (like "Barack Obama") and put it in a variable:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
scanf("%s", name);
printf("Your Name is: %s", name);
return 0;
}
Output:
Enter your name: Barack Obama
Your Name is: Barack
How can I make the program read the whole name?
Use:
fgets (name, 100, stdin);
100 is the max length of the buffer. You should adjust it as per your need.
Use:
scanf ("%[^\n]%*c", name);
The [] is the scanset character. [^\n] tells that while the input is not a newline ('\n') take input. Then with the %*c it reads the newline character from the input buffer (which is not read), and the * indicates that this read in input is discarded (assignment suppression), as you do not need it, and this newline in the buffer does not create any problem for next inputs that you might take.
Read here about the scanset and the assignment suppression operators.
Note you can also use gets but ....
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Try this:
scanf("%[^\n]s",name);
\n just sets the delimiter for the scanned string.
Here is an example of how you can get input containing spaces by using the fgets function.
#include <stdio.h>
int main()
{
char name[100];
printf("Enter your name: ");
fgets(name, 100, stdin);
printf("Your Name is: %s", name);
return 0;
}
scanf(" %[^\t\n]s",&str);
str is the variable in which you are getting the string from.
The correct answer is this:
#include <stdio.h>
int main(void)
{
char name[100];
printf("Enter your name: ");
// pay attention to the space in front of the %
//that do all the trick
scanf(" %[^\n]s", name);
printf("Your Name is: %s", name);
return 0;
}
That space in front of % is very important, because if you have in your program another few scanf let's say you have 1 scanf of an integer value and another scanf with a double value... when you reach the scanf for your char (string name) that command will be skipped and you can't enter value for it... but if you put that space in front of % will be ok everything and not skip nothing.
NOTE: When using fgets(), the last character in the array will be '\n' at times when you use fgets() for small inputs in CLI (command line interpreter) , as you end the string with 'Enter'. So when you print the string the compiler will always go to the next line when printing the string. If you want the input string to have null terminated string like behavior, use this simple hack.
#include<stdio.h>
int main()
{
int i,size;
char a[100];
fgets(a,100,stdin);;
size = strlen(a);
a[size-1]='\0';
return 0;
}
Update: Updated with help from other users.
#include <stdio.h>
// read a line into str, return length
int read_line(char str[]) {
int c, i=0;
c = getchar();
while (c != '\n' && c != EOF) {
str[i] = c;
c = getchar();
i++;
}
str[i] = '\0';
return i;
}
Using this code you can take input till pressing enter of your keyboard.
char ch[100];
int i;
for (i = 0; ch[i] != '\n'; i++)
{
scanf("%c ", &ch[i]);
}
While the above mentioned methods do work, but each one has it's own kind of problems.
You can use getline() or getdelim(), if you are using posix supported platform.
If you are using windows and minigw as your compiler, then it should be available.
getline() is defined as :
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
In order to take input, first you need to create a pointer to char type.
#include <stdio.h>
#include<stdlib.h>
// s is a pointer to char type.
char *s;
// size is of size_t type, this number varies based on your guess of
// how long the input is, even if the number is small, it isn't going
// to be a problem
size_t size = 10;
int main(){
// allocate s with the necessary memory needed, +1 is added
// as its input also contains, /n character at the end.
s = (char *)malloc(size+1);
getline(&s,&size,stdin);
printf("%s",s);
return 0;
}
Sample Input:Hello world to the world!
Output:Hello world to the world!\n
One thing to notice here is, even though allocated memory for s is 11 bytes,
where as input size is 26 bytes, getline reallocates s using realloc().
So it doesn't matter how long your input is.
size is updated with no.of bytes read, as per above sample input size will be 27.
getline() also considers \n as input.So your 's' will hold '\n' at the end.
There is also more generic version of getline(), which is getdelim(), which takes one more extra argument, that is delimiter.
getdelim() is defined as:
ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *stream);
Linux man page
If you need to read more than one line, need to clear buffer. Example:
int n;
scanf("%d", &n);
char str[1001];
char temp;
scanf("%c",&temp); // temp statement to clear buffer
scanf("%[^\n]",str);
"%s" will read the input until whitespace is reached.
gets might be a good place to start if you want to read a line (i.e. all characters including whitespace until a newline character is reached).
"Barack Obama" has a space between 'Barack' and 'Obama'. To accommodate that, use this code;
#include <stdio.h>
int main()
{
printf("Enter your name\n");
char a[80];
gets(a);
printf("Your name is %s\n", a);
return 0;
}
scanf("%s",name);
use & with scanf input

Resources