I'm trying to print a string of chars from an array and end the loop whenever I press the "Enter" key.
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
{
scanf(" %c", &charArry[i]);
}
for (i = 0; i < MAXARY; i++)
{
printf(" %c", charArry[i]);
}
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop. Any suggestions?
P.S
MAXARY is a constant for the array length, currently 20.
Your close to having this working. Whilst I agree the use of scanf should be avoided, see: Why does everyone say not to use scanf? What should I use instead?, the reason your program doesn't do what you expect is due to a logic error.
Your for loop states:
for (i = 0; i < MAXARY && charArry[i] != 13; i++)
Now recapping how a for loop works, you have:
1. initalization (i=0)
2. conditional check (i < MAXARY && charArry[i] != 13)
3. conditional block (scanf)
4. increment (i++)
5. return to 2
You'll note your charArray[i] != 13check is happening after i has been incremented. Hence your not checking against the character you just read but the next character in charArray[i]. This is why your never breaking your loop at the \r character.
A recommended fix would be:
for (i = 0; i < MAXARY; i++)
{
int result = scanf("%c", &charArry[i]);
if( result != 1 || charArry[i] == '\n' )
break;
}
Which checks scanf was successful and charArry when i is the character that was read.
Also note as chux has pointed out the \r character is a carrage return, not the newline. Hence this check will only work if your working on windows (as unix doesn't use \r). If you want to be platform independant use \n
For some reason whenever I press the Enter key it just goes to a new line instead of breaking the loop.
The space in the format scanf(" %c", &charArry[i]); directs scanf() to consume and discard all optional leading white-space. charArry[i] will never be assigned 13 as 13 is typically '\r', a white-space.
An enter key is usually translated to '\n'.
Do not test values that have not been assigned #Red Alert
// v---------v not assigned yet.
for (i = 0; i < MAXARY && charArry[i] != 13
Repaired code
int i;
char charArry[MAXARY];
printf("Input an array of chars: \n\n");
for (i = 0; i < MAXARY; i++) {
if (scanf("%c", &charArry[i]) != 1) break; // End of file or error occurred
// If enter key encountered
// Usualy the charArry[i] == '\r' is not needed.
if (charArry[i] == '\n' || charArry[i] == '\r') break;
}
// Only print out characters that were read.
int j;
for (j = 0; j < i; j++) {
printf("%c", charArry[j]);
}
Related
I've encountered a problem while trying to scan chars into an array.
This is the scan loop -
char letter[6] = {0};
for(int i = 0; i <= 5; i++)
{
scanf(" %c", &letter[i]);
}
The desired result is that if the input is shorter than 6 every element which doesn't receive a value from scanf while remains 0.
However if I try to input for example 3 chars I cannot continue in the program.
On the other hand when I try to input 3 chars from txt file the program works and I achieve the desired result.
I was wondering what is the correct way to fix this issue.
Thank you all in advance.
Code fails to detect '\n' (Enter) due to space in format.
" " in scanf(" %c",&letter[i]); consumes and discards all white space including '\n' so code loses a way to detect end-of-line.
Instead check if scan failed (stdin closed or rare input error) or if a '\n' was read, then break the loop.
for(int i=0; i<=5; i++) {
char ch;
if (scanf("%c", &ch) != 1 || ch == '\n') {
break;
}
letter[i] = (char) ch;
}
To insure letter[] is a string, leave the last element as a null character.
// for(int i=0; i<=5; i++) {
for(int i=0; i < 5; i++) {
I am taking input in an array of length 100 using scanf in a loop. After 20 numbers, if I enter -1, I want the loop to exit, i.e finish taking input and continue with the rest of the program. I am doing something like this
for(i=0;i<100;i++)
{
scanf("%d", &input[i]);
if(input[i] == -1)
{
break;
}
}
I heard, it is bad practice to use break statements even though this code works perfectly fine. So I was wondering what is a more efficient way to end the loop when -1 is entered. I tried
for(i=0;scanf("%d",&input[i])!=-1;i++)
also
fori(i=0;i<100;i++){
do
{scanf("%d", &input[i]);
}while(input[i]!=-1
}
Neither of these don't work
The second expression of the for loop is a free-form boolean expression. In this case you could add your condition there. However in this case it wouldn't look exactly nice. For example
for(i=0; i < 100 && (i < 1 || input[i - 1] != -1); i++)
{
scanf("%d", &input[i]);
}
I.e. if we have already input one value, check the value and that must be inequal to -1 for the loop to continue
Another would be to use a synthetic flag variable:
int loop_again = 1;
for (i = 0; loop_again && i < 100; i++) {
scanf("%d", &input[i]);
if(input[i] == -1)
{
loop_again = 0;
}
}
All in all, these both look way uglier than just using the break statement for the very thing that it was invented for.
Note that you also should check the return value of scanf itself!
it is bad practice to use break statements
As Ancient Greeks said, "Pan Metron Ariston", which means that everything that is used with balance is great. This applies here too, and your code as is, is good to go. The only thing to be worried about is not checking the return value of scanf().
Now if you really insist on changing your approach, then please refer to Haapala's answer, we got there first.
You can use a while loop and check for -1 in the input in the loop conditional. Note that you should always check the value returned by scanf(). In the posted code, non-numeric input results in no value being stored in input[]; this may lead to undefined behavior later if the code attempts to use an indeterminate value.
Here is an example. Note that the loop conditional first checks whether the array index has grown too large, then checks the return value from scanf() to be sure that a number was entered, then checks to see if -1 was entered. In the case of non-numeric input, the loop is terminated.
#include <stdio.h>
#define INPUT_SZ 100
int main(void)
{
int input[INPUT_SZ];
size_t i = 0;
while (i < INPUT_SZ && scanf("%d", &input[i]) == 1 && input[i] != -1) {
++i;
}
puts("You entered:");
for (size_t j = 0; j < i; j++) {
printf("%d\n", input[j]);
}
return 0;
}
Sample interaction:
2 4 6 8 -1
You entered:
2
4
6
8
You can simply change the value of counter variable to max, then it'll automatically come out of loop.
#include<stdio.h>
#define MAX 10
int main()
{
int ar[MAX], i, count;
for(i=0; i<MAX; i++)
{
scanf("%d", &ar[i]);
if(ar[i]==-1)
{
count=i--; //this is your new MAX. Not mandatory but will be useful if you need to access array elements
i=MAX;
}
}
//printing array
for(i=0; i<count; i++)
{
printf("Element %d: %d\t", i+1, ar[i]);
}
return 0;
}
Hope this helps.
Use a do-while loop
int i=0;
do{
if(scanf("%d", &input[i++]) != 1)
{
if(i>0)
--i; // Decrementing i if an integer is not provided
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) // Wasting the buffer
;
}
}while(input[i-1] != -1 && i<=99);
So I'm passing an string into this function, where the length of the array is at a default of 50.
I input the string using this
void inputDNA(char *dnaSequence)
{
printf("Enter the sequence.");
scanf("%s", dnaSequence);
}
So I figured /n would be in the last position of the array if its less than 50. So I have this for loop...
for(i = 0; i<length || dnaSequence[i] == '\n'; i++)
{
switch(dnaSequence[i])
{
case 'A': aCount++;
break;
case 'a': aCount++;
break; //do this for g,c,t but for readability I removed them for this post.
default:
{
printf("Invalid Base %c\n", dnaSequence[i]);
break;
}
}
}
To read the string and count all a,g,t,c but print out any invalid bases. It does this till it finds the /n or it reaches the end of the array. It does it correctly for the string I entered, but then it just throws in random characters from the rest of the array for the last half and calls them all invalid if they are.
So just to illustrate what I'm talking about, here it is in action. Image
Any help?
The memory reserved for dnaSequence is dirty. scanf puts the read characters at the beginning but the end stays the same. You should check for the end of the c-string in the for loop.
for(i = 0; i<length && dnaSequence[i] != '\n' && dnaSequence[i] != '\0'; i++)
EDIT: Tt worth to mention that scanf does not read the end-of-line character \n. So checking for it is unnecessary.
for(i = 0; i < length && dnaSequence[i] != '\0'; i++)
Your logic in your for statement is bad. Your for will end when the conditional part of your for loop returns false.
Remember that for's syntax is:
for(initialization; conditional; increment)
Your conditional should be using an And, not an Or, since i
Try
for(i=0; i<length && dnaSequence[i] !='\0'; i++)
I wrote the following code to accept characters from user and enter into an array till he inputs a free space (' ') or a line \n. But code is not functioning. As in, when space bar or return key is pressed in the input, my computer is still accepting values without exiting the loop.
char X[99];
printf ("Type the string without spaces\n");
for (i=0;i<99;i++) {
scanf ("%c",&m);
if(m!=' '&&m!='\n')
X[i]=m;
else i=99;
}
Please explain the error.
First the issue: the default tty mode is canonical, meaning input is made available line by line (see man termios)
Once you fix that, you can use getchar() or read() to get one character at a time. The tty setting, example straight out of the man page of termios .
#include <stdio.h>
#include <termios.h>
int ttySetNoncanonical(int fd, struct termios *prev)
{
struct termios t;
if (tcgetattr(fd, &t) == -1)
return -1;
if (prev != NULL)
*prev = t;
t.c_lflag &= ~ (ICANON);
t.c_cc[VMIN] = 1; // 1-char at a go
t.c_cc[VTIME] = 0; // blocking mode
if (tcsetattr(fd, TCSAFLUSH, &t) == -1)
return -1;
return 0;
}
void main(void) {
printf ("\nType the string without spaces\n");
ttySetNoncanonical(0,NULL); // set to non-canonical mode
char X[1000];
int m, ec=0;
int i;
X[0] = 0;
for (i=0;i<1000;i++) {
//ec = read(0,X+i,1); // read one char at a time
m = getchar();
if(m == EOF || m==' ' || m=='\n') {
X[i] = 0;
break;
}
X[i] = m;
}
printf("You entered %s. Bye.\n\n", X);
}
HTH. You might want to check the boundary condition, in case your user typed in 1000 characters. It works for me on a GNU Linux.
use getch(), scanf() will not work that way.
it would be something like :
for(i=0;i<99;i++)
{
char ch=getch();
if(m!=' ' && m!='\n' && m!='\r')
X[i]=m;
else i=99;
printf("%c",ch);
}
The scanf function reads and ignores any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters). So, instead of
scanf("%c",&m);
use
m = getchar();
The function int getchar ( void ); gets character from stdin, returns the next character from the standard input (stdin). It is equivalent to calling getc with stdin as argument.
Also, the condition should use logical-AND as in:
if(m!=' '&& m!='\n')
Also, outside the loop, write,
X[i] = '\0';
Lets look into the if condition
if(m!=' '||m!='\n')
1. When m is space m=' ' (i.e. ASCII value 32)
m=' '
As per your if condition (Cond1 || Cond2), Cond1 will fail and o/p will be 0 but Cond2 will be TRUE, because it is not ' '.
if(FALSE || TRUE)
will be if(TRUE).
When your input is newline (i.e ASCII value 10).
m='\n'
Here Cond1 will be TRUE because it is not SPACE, due to this it will not check the second condition as per C. and will execute the if(TRUE) statement.
Please try to code it by yourself.... It will help you to clear few C doubts and u will get to know how || and && condition works.
Better to use getchar() instead of scanf in here as you read character by character. Usually we use scanf for get strings as input.
Using the logical operators: && (AND) operator checks for one condition to be false, while or || (OR) operator checks for one condition to be true. So if you use && operator, it checks whether it is a space, and if not, it returns false, without even checking the second condition(EOF). But if you use || operator, as used below, it checks for both cases. Check for more details in operators here
You also have to increment the counter (i) after adding an item to the array (Inside the if) as if you don't, it will continuously add items to the same place of the array, which means you will lost the precious inputs.
So, here's my code:
char X[99];
char m;
printf ("Type the string without spaces\n");
for (i=0;i<99;i++) {
m = getchar();
if(m == ' ' || m=='\n') {
X[i]=m;
i++;
}
else i=99;
}
With the function getch(); it ends if your pressing space or enter!
#include <stdio.h>
int main(void) {
char m, X[99];
int i;
printf("Type the string without spaces\n");
for (i = 0; i < 99; i++) {
m = getch();
if (m == ' ' || m == '\n' || m == '\r')
i=100;
else
X[i] = m;
printf("%c", m);
}
}
try this
#include <stdio.h>
int main(){
int i;
char m, X[99];
printf("Type the string without spaces\n");
for (i=0;i<98;i++){//98 --> sizeof(X) -1
scanf("%c",&m);
if(m!=' ' && m!='\n')
X[i] = m;
else
break;
}
X[i] = '\0';
puts(X);
return 0;
}
Here's a working code:
#include <stdio.h>
int main ()
{
char x[100] = {0};
char m;
int i, j;
printf ("Type:\n");
for (i=0; i<99; i++) {
m = getchar();
getchar();
if ((m != ' ') && (m != '\n')) {
x[i] = m;
} else {
printf ("Breaking.");
break;
}
}
printf ("\n");
for (j=0; j<i; j++)
printf ("%c\n", x[j]);
return 0;
}
Here I have used an extra getchar() to consume the newline used to enter the character m. And so (please note) you will also need to enter a newline after a space (' ') and a newline ('\n') to enter and store these in m and compare them in the next lines.
First error, as everyone has pointed out is the logical operator in the if() statement. It should be
if(m!=' ' && m!='\n')
As you want to check if the entered character is neither a (space) nor a \n, so you have to use the && operator.
Next, the error you are getting is because of something called the trailing character. When you enter a letter and press enter (at the point where your scanf("%c",&m) is asking for input). That letter gets stored in the variable m, but the newline character \n caused by the enter pressed is still in the stdin. That character is read by the scanf("%c",&m) of the next iteration of the for loop, thus the loop exits.
What you need to do is consume that trailing character before the next scanf() is executed. for that you need a getchar() which does this job. So now your code becomes something like this..
#include<stdio.h>
int main()
{
char X[99];
char m;
int i;
printf("Type the string without spaces\n");
for (i=0;i<99;i++)
{
scanf("%c",&m);
if(m!=' ' && m!='\n')
{
X[i]=m;
getchar(); // this statement is consuming the left out trailing character
}
else
i=99;
}
printf("%s",X);
}
Now, the program works exactly as you want.
just starting C and want to know how to enter an unknown numbers of char into array,
when the finishing symbol will be '~'
#include <stdio.h>
#define N (499)
int main()
{
int count;
int i;
char input;
char text[N];
printf("Text:\n");
scanf("%c", &input);
while (input != '~')
{
for(i = 0; i < N; i++)
{
text[i] = input;
scanf("%c", &input);
count++;
}
}
return 0;
}
But i keep getting an infinite loop
thanks!
Remove the while loop and replace the for loop with:
for(i = 0; i < N && input != '~'; i++)
Also it is a good idea to finish your string with a terminating null character so the program knows where the string ends.
So after the for loop add:
text[i] = '\0';
Alternatively you can use some scanf regex to avoid loops alltogether.
For example:
scanf("%498[^~]", text);
will read 498 characters in the array text until the ~sign is met. It will also put the terminating character to the string.
(you should not usually use scanf, but it is good enough for a beginner)
Edit: thanks to some random guy, "amis" or smth(please tell your name) a mistake replaced.
You have 2 loops. If the first one is not elapsed (because you get less chars than N), you never return to the first one, when you test input.
More than that, the last char you read will usually be a \n, so you won't get a ~in the first loop level
If you are using count for counting initialize it to zero first.
int count = 0;
You are using for loop inside a while loop, for every character input the for loop will run N times. so check input != '~' in for loop itself, Remove while loop.
Instead of your looping method, Try this-
for(i = 0; i < N && input != '~'; i++)
{
text[i] = input;
scanf(" %c", &input); // Note the space before ' %c'
count++;
}
text[i]='\0'; // To make the last byte as null.
You need give a space before %c if you use it in loops, else you can read only N/2 input from the user!
It is due to \n after the input character. After your input when you hit enter \n is read as a next input, to avoid this give a space before %c!
Output( No space before %c )-
root#sathish1:~/My Docs/Programs# ./a.out
Text:
q
w
e
r
t
y
~
Count = 12
Output( With a space before %c )-
root#sathish1:~/My Docs/Programs# ./a.out
Text:
q
w
e
r
t
y
~
Count = 6
Note the count difference!