I'm new to C and I would like to know if it's possible to write into a string the character \n from the keyboard by using scanf() function.
The code that I'm using is this: (sorry for the Italian variables words)
void riempi_array_stringhe (char* stringhe[], int lunghezza_array)
{
for (int i = 0; i < lunghezza_array; i++) {
stringhe[i] = (char*) malloc(sizeof(char) * 100);
printf("Insert a new string: ");
scanf("%s", stringhe[i]);
}
}
I tried type shift + enter, alt + enter, or to insert \n as input but not works at all.
Thanks in advance!
There is a [ specifier. Quote from scanf(2)
[ — Matches a nonempty sequence of characters from the specified set of accepted characters; the next pointer must be a pointer to char, and there must be enough room for all the characters in the string, plus a terminating null byte.
Example:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *str[10];
for (int i = 0; i < 10; i++) {
str[i] = (char *)malloc(sizeof(char) * 100);
printf("Insert a new string: ");
scanf("%[^~]", str[i]);
printf("Your input: %s\n", str[i]);
}
return 0;
}
To end the input we should input ~ and then Enter or press Ctrl+D (EOF). We can specify other characters to terminate the input. For example, scanf("%[^X]", str[i]); will terminate the input after user inserts an X and then Enter.
Please note, to prevent your buffer overrun, you should always specify the width of the sequence equals to the buffer size minus one (for NUL character), i.e.:
scanf("%99[^~]", str[i]); // read no more than 99 symbols + NUL
Related
I am currently on a beginner course in C and was given an exercise requiring my program to check if the user input contains non-alphabets. I've figured to use the function isalpha() to check the user input and if it contains non-alphabets, the program should ask the user to enter another input.
Below is my current code:
#include <stdio.h>
#include <ctype.h>
#define MAX 13
int main() {
char player1[MAX];
int k = 0;
// Ask player 1 to type a word.
printf("Player 1, enter a word of no more than 12 letters: \n");
fgets(player1, MAX, stdin);
// // Loop over the word entered by player1
for (int i = 0; i < player1[i]; i++) {
// if any chars looped through is not an alphabet, print message.
if (isalpha((unsigned char)player1[i]) == 0) {
printf("Sorry, the word must contain only English letters.");
}
}
However, after testing it, I've derived a few cases from its results.
Case 1:
Entering without any input prints ("Sorry, the word must contain only English letters. ")
Case 2:
An input with 1 non-alphabetic character prints the 'sorry' message twice. Additionally, an input with 2 non-alphabetic characters print the 'sorry' message thrice. This implies that case 1 is true, since no input prints the message once, then adding a non-alphabetic prints the message twice.
Case 3:
An input of less than 10 characters(all alphabetic) prints out the sorry message also.
Case 4:
An input of more than 9 characters(all alphabetic) does not print out the sorry message, which satisfies my requirements.
Why are these the cases? I only require the message to print once if after looping through the user input, there's found to be a non-alphabetic character!
As #unwind has noted, the conditional of the OP for() loop is incorrect.
Good to trust to isalpha() but your code doesn't have to fondle each and every character. Another standard library function, strspn(), when supplied with your needs, can perform the looping work for you.
#include <stdio.h>
#include <string.h>
#define MAX 12
int main() {
char player1[ MAX + 1 + 1 ]; // buffer size for fgets() 12 + '\n' + '\0'
char *permissible =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Ask player 1 to type a word.
printf("Player 1, enter a word of no more than %d letters: \n", MAX);
fgets(player1, sizeof player1, stdin);
if( player1[ strspn( player1, permissible ) ] != '\n' )
printf("Sorry, the word must contain only English letters.");
return 0;
}
Strings in C are null-terminated, which means they contains an extra byte '\0' to mark the end of the string (character 0 in the ascii table), so you can only store 12 characters in a char array of size 13.
If you array contains a string smaller than 12 characters, since you loop over the whole array, you'll meet that null-terminating-byte, which fails isalpha(): it checks if character is in range ['A', 'Z'] or ['a', 'z']. Characters are just integers for your computers, so isalpha() checks if received value is is range [65, 90] or [97, 122], and 0 is not.
To be more precise, the notion of integer makes no sense for your computer, that's just how we interpret information, it's just a bunch of bits for your computer.
See ascii table: https://www.rapidtables.com/code/text/ascii-table.html
By having a fixed size buffer, you'll have garbage after the contained string if the string doesn't take all the space.
You have 2 conditions to stop iterating:
end of array, to prevent overflowing the array
end of string, to prevent mis-interpreting bytes in array which are further than string end
Error message might be printed several times, since you keep checking even after an error occured, you have to break the loop.
Below code doesn't meet mentioned problems
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define BUFFER_SIZE 13
#define MIN(a, b) (a < b ? a : b)
int main(void)
{
char player1[BUFFER_SIZE];
int maxIndex;
int i;
/* Ask player 1 to type a word */
printf("Player 1, enter a word of no more than 12 letters: \n");
fgets(player1, BUFFER_SIZE, stdin);
/*
* Max index for iteration, if string is lesser than 12 characters
* (excluding null-terminating byte '\0') stop on string end, otherwise
* loop over whole array
*/
maxIndex = MIN(strlen(player1) - 1, BUFFER_SIZE);
for (i = 0; i < maxIndex; i++) {
/* Print error if non-letters were entered */
if (isalpha(player1[i]) == 0) {
printf("Sorry, the word must contain only English letters.");
/* Error occured, no need to check further */
break;
}
}
/*
for (i = 0; i < maxIndex; i++)
printf("%d ", (int) player1[i]);
printf("\n%s\n", player1);*/
return 0;
}
The MIN() is a macro, a ternary expression which returns the smallest argument, nothing really complicated here.
But note that, when you enter the word, you press <Enter>, so your string contains a "go to next line" character (character '\n', n°10 in ascii table, as #Shawn mentioned in comments), so you have to stop before it: that's why I use strlen(player) - 1, string ends with "\n\0", and strlen() returns the number of bytes before '\0' (including '\n').
I've let a dump of the string at the end, you can modify the end-index there to see what's sent to isalpha(), replace maxIndex with BUFFER_SIZE.
This:
for (int i = 0; i < player1[i]; i++) {
loops from 0 up until (but not including) the code point value of the i:th character, updating i every time it loops. It will very likely access outside the array bounds, which is undefined behavior.
It should look for the terminator (or linefeed but let's keep it simple):
for (size_t i = 0; player1[i] != '\0'; ++i) {
to use the function isalpha() to check the user input and if it contains non-alphabets
Simply read one character at a time. No maximum needed.
#include <ctype.h>
#include <stdio.h>
int main(void) {
int ch;
int all_alpha = 1;
printf("Player 1, enter a line\n");
while ((ch = getchar()) != '\n' && ch != EOF) {
if (!isalpha(ch) {
all_alpha = 0;
}
}
if (!all_alpha) {
printf("Sorry, the line must contain only letters.");
}
}
I solved the question but still have a doubt
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argv, char *argc[])
{
if (argv != 2)
{
printf("Invalid Input, Please enter the length of the strings you wish to compare\n");
return 1;
}
int n = atoi(argc[1]);
char *a = malloc((sizeof(char) * n));
printf("Enter the first string - ");
fgets(a, n + 1, stdin);
getc(stdin);
char *b = malloc((sizeof(char) * n) + 1);
printf("Enter second string - ");
fgets(b, n + 1, stdin);
int d = 0;
for (int i = 0; i < n; i++)
{
if (*(a + i) != *(b + i))
{
d++;
}
}
if (d == 0)
{
printf("The two strings are identical\n");
}
else
{
printf("The two strings are not identical\n");
}
free(a);
free(b);
}
My problem was solved after i added getc(stdin);
But can someone please tell me what exactly it is doing? I don't know why it works!
fgets stops reading after input once it sees a newline (which isn't consumed if the buffer doesn't have enough space). So newline from first input is left in the input stream, which the second call to fgets sees and stops reading input.
When you add getc(stdin);, it consumes the leftover newline char, so it works.
As noted in comments, you're allocating only n bytes for a but attempting to read upto n + 1 bytes. This is undefined behaviour. So you'd need add " + 1" to the malloc call (like you do for the allocation of b).
Another problem that you need to be aware of is, fgets will read the newline character too into a and b if the they have enough space (e.g. you enter just "hi" and n is 10).
And another problem is that if input given is less than n, you loop still compares n chars. This could be undefined as the rest of buffers are uninitialized.
You can also break out of the loop immediately when there's a mismatch. No need compare the rest of the chars.
I mixed up two programs in the cs50 sandbox, one was to find the the number of characters in an array and other was the print these characters. I know the program is garbage but could anyone explain me what is the compiler doing here?
When I ran this, the output starts printing alphanumeric text and never stops Thanks
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
int n = 0;
while (strlen(s) != '\0')
{
n++;
printf("%c", n);
}
}
You have multiple problems with the code you show, here's a couple of them:
strlen(s) will never be zero as you never modify or remove characters from the string, which means you have an infinite loop
n is an integer and not a character so should be printed with the %d format specifier
'\0' is (semantically) a character, representing the string terminator, it's not (semantically) the value 0
To fix the first problem I suspect you want to iterate over every character in the string? Then that could be done with e.g.
for (int i = 0; i < strlen(s); ++i)
{
printf("Current character is '%c'\n", s[i]);
}
But if all you want is to could the number of characters in the string, then that's what strlen is already gives you:
printf("The number of characters in the string is %zu\n", strlen(s));
If you want to count the length of the string without using strlen then you need to modify the loop to loop until you hit the terminator:
for (n = 0; s[n] != '\0'; ++n)
{
// Empty
}
// Here the value of n is the number of characters in the string s
All of this should be easy to figure out by reading any decent beginners book.
while (strlen(s) != '\0') is wrong. '\0' equals 0. There string length is never 0, so the loop keeps going on forever, printing integers interpreted as characters.
You can either use the indexes to go through the string characters by using the variable "n" or you can increment the pointer of the string that you have received from the standard input to go through all of its characters.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Name: ");
/* First way using n to iterate */
int n = 0;
for (n = 0; n < strlen(s); ++n)
{
printf("%c", s[n]);
}
printf("\n");
/* Second way increment the string pointer*/
while (strlen(s) != '\0')
{
printf("%c", *s); //print the value of s
s++; // go to the next character from s
}
printf("\n");
return 0;
}
I'm new to C and have been set the following problem. I am to write a program where a string can be entered and stored, I should then enter two integer values which will then be used to remove characters from the string, afterwards the result should be printed. Once the program works it should be converted into a function.
I have created a program that will split the entered string into two strings which store the chars I want to keep in two buffers, afterwards the two strings are concatenated to give the resultant edited string. The problem I am having is that when I print the edited string I get random characters at the end and sometimes in between the two strings and I think it's because the strings are not being null terminated correctly. I hope that someone is able to help, Thanks :)
#include <stdio.h>
#include <string.h>
int main ()
{
char string [25];
char buffer1 [25];
char buffer2 [25];
int start;
int remove;
int i;
int finish;
int size;
int numbercopy;
int A, B, C;
printf("Enter a string: ");
gets(string);
printf("\nEnter a starting character position: ");
scanf("%d", &start);
printf("\nHow many characters would you like to remove? ");
scanf("%d", &remove);
finish = (start+remove);
size = strlen(string);
numbercopy = (size-finish);
strncpy(&buffer1[0], &string[0], start);
buffer1[start] = '\0';
strncpy(&buffer2[0], &string[finish], numbercopy);
buffer2[numbercopy] = '\0';
A = strlen(buffer1);
B = strlen(buffer2);
C = (A+B);
strcat(buffer1, buffer2);buffer1[C] = '\0';
for (i=0; i<25; i++)
{
printf("%c", buffer1[i]);
}
return 0;
}
Since it is a string, you do not need to print it character by character. Also, the loop indicates that only 25 char strings will be printed. If a string (buffer1) is shorter in length(<25), garbage values will be printed, if a string is is larger (>25), some chars will not be printed.
Change this:
for (i=0; i<25; i++)
{
printf("%c", buffer1[i]);
}
to this:
printf("%s", buffer1);
I want to write a program in C that fills an array p[MAX][N] of strings
I used this but i dont know which is the null string to enter when i give input.
#include <stdio.h>
#include <string.h>
#define R 3
#define C 8
int main()
{
int i;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && gets(strings[i]));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
puts(strings[i]);
return 0;
}
First, never use gets(). It is inherently dangerous as it doesn't do any bounds checking on the memory you pass to it. Use fgets() instead:
for (i = 0; i < R && fgets(strings[i], C, stdin); ++i);
Note that fgets() will leave any new line ('\n') in the input at the end of the string, assuming that the whole line can fit in your buffer. If the whole line can't fit in your buffer, then it reads as much as can fit into your buffer (leaving room for and always appending a nul terminator), stops reading the input at that point and leaves the rest of the input on the stream. With C being so small in your program, such an occurrence is quite likely.
Alternatively, you could use getline() if it's available on your platform:
char *strings[R] = { 0 };
size_t cap;
for (i = 0; i < R && 0 <= getline(&strings[i], (cap = 0, &cap), stdin));
if (i == R)
printf("\n**Table Full - input terminated \n");
for (i = 0; i < R && strings[i]; ++i)
puts(strings[i]);
/* program done; clean up strings */
for (i = 0; i < R && strings[R]; ++i)
free(strings[R]);
getline() automatically dynamically (re)allocates the memory necessary to fit the next line from the input stream. It also leaves any new line ('\n') in the input at the end of the string.
Second, ctrl-D is typically used terminate the input to a program from a terminal.
It worked. I changed it to this
int main()
{
int i,j,max,thesi,sum=0,countCH=0,mikos=0;
char strings[R][C];
printf("***Table of Strings - Names***\n\n");
for(i=0;(i<R && fgets(strings[i],C,stdin ));i++)
;
if(i==R)
printf("\n**Table Full - input terminated \n");
for(i=0;i<R;i++)
fputs(strings[i],stdout);
//Euresh megistou string
max=0;
sum=0;
for(i=0;i<R;i++)
{
mikos=strlen(strings[i])-1;
sum+=mikos;
if(mikos>max)
{
max=mikos;
thesi=i;
}
}
printf("\nTo string me to megalitero mikos einai auto pou brisketai sthn %d seira \nkai einai to %s \nme mhkos %d",thesi+1,strings[thesi],max);
printf("\nO pinakas me ta strings periexei %d xaraktires\n",sum);
return 0;
}
It works just fine only that strlen counts all the chars of the string including null char why is that i dont get it?