Print output just beside the user input - c

According to the question, The user needs to enter the no of hours the vehicle is parked and the total charge for the hours should get printed beside it.
for example:
I created this simple program
#include<stdio.h>>
#include<math.h>
float calculateCharges(float hurs);
int main()
{
float hours;//total no of hours vehicle is parked
int i;
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
printf("\t%f\n", calculateCharges(hours));
}
getch();
return 0;
}
float calculateCharges(float hurs)
{
float charges;
hurs = ceil(hurs);
if (hurs >= 24) charges = 10;
else
{
if (hurs <= 3) charges = 2;
else
{
hurs = hurs - 3;
charges = 2 + 0.5*hurs;
}
}
return charges;
}
But now every time I enter hours the charges are getting printed below it instead of beside it. As shown in the image:
Is there is a way to consume the newline after scanf? So that charges can be printed beside the scanf?
I have modified my code this way too, but it didn't make any difference.
printf("%s%10s%10s", "Car", "Hours", "Charges");
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
printf("\t%f\n",(scanf("%f", &hours),calculateCharges(hours)));
}
Let me know if the original question is required. I'm using Visual studio 2017 RC.

You can use something like this:
#include <iostream>
#include <windows.h>
//This will set the position of the cursor
void gotoXY(int x, int y) {
//Initialize the coordinates
COORD coord = {x, y};
//Set the position
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
return;
}
void getCursorXY(int &x, int&y) {
CONSOLE_SCREEN_BUFFER_INFO csbi;
if(GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) {
x = csbi.dwCursorPosition.X;
y = csbi.dwCursorPosition.Y;
}
}
I found it here.
As already written in one of the answers this solution is not platform independent.
But i guess there are similar solutions on other platforms and you can easy set the cursor on the position you want.
Example usage in your main:
for (i = 1; i <= 3; i++)
{
printf("\n%d\t", i);
scanf("%f", &hours);
gotoXY( 20, i + 1);
printf("\t%f\n", calculateCharges(hours));
}
Workarounds for scanf can be found here.

scanf_s always generates a new line upon enter and unfortunately other user input capturing platform independent functions I know of (getc & getchar) do so too. Anyway on Windows it could be done using _getch() from conio header.
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
int getIntFromUser()
{
char readCharacters[10];
int index = 0;
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
{
if (currentChar == EOF)
{
// Some error that shouldn't occour in your simple homework program
}
if (index > 9)
{
// Another possible error case where you would start to write beyond 'readCharacters' array
}
// We might as well disallow anything but digits, enter & backspace (You don't need anything else, do you?)
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
}
if (index == 0)
{
// User pressed enter without having entered a number, let's give him a zero then
return 0;
}
readCharacters[index] = '\0';
int retVal = atoi(readCharacters);
// Worth noting that the value of converted user given string shouldn't be greater than what a signed int can hold
return retVal;
}
int main(int argc, char* argv[])
{
// Unlike scanf_s this will not generate a new line on enter
printf("getIntFromUser() sample (enter a number)\n");
int someValue = getIntFromUser();
printf(" -- This will be printed on the same line. (someValue is %d)\n\n", someValue);
// scanf_s sample
int anotherValue;
printf("scanf_s() sample (Insert a number.)\n");
scanf_s("%d", &anotherValue);
printf("This will be printed on a new line\n\n");
printf("Press any key to exit.");
_getch();
return 0;
}
EDIT
I feel like the above would become less readable if I were to add a comment over every code line. Instead I'm going to paste some blocks of code 1 by 1.
But first about the _getch function: It waits for the user to type something into the console and then returns the user given char as an int. char implicitly converts to int, so you may compare the _getch result to a character as I did many times in getIntFromUser (e.g. if (currentChar == '\b') { ... }).
You should also know about the values a char can hold and what their values are as an int (check out http://en.cppreference.com/w/cpp/language/ascii).
Going by the table the char '0' would be value 48 as an int, which is what _getch would return if the user were to type a 0.
First declare an array/string of 10 elements. Hope you know about them already. In this case the array is basically a chain of 10 elements that are all of type char, which are also referred to as string.
char readCharacters[10];
An indexer for the string is required.
int index = 0;
Below we have the usual for loop that...
1st: creates a variable of type int and assigns the result of _getch to it.
2nd: will determine if the loop shall keep executing. In this case the loop will break when currentChar is not '\r', which is an escape sequence that represents enter as a character.
3rd: will execute stuff inside once and then update currentChar with a new _getch.
for (int currentChar = _getch(); currentChar != '\r'; currentChar = _getch())
Checks if the user input (retrieved via _getch) is smaller than '0' (value 48 as an int) and greater than '9' (value 57 as an int). If either of them is true it will additionally check if the value of currentChar is not '\b' (value 8 as an int), which is the escape sequence for a backslash.
When that additional check evaluated to true as well then the keyword continue is used. Meaning that the rest of the block in the loop is not executed and instead the loop will start at the top again by getting a new user input and evaluating if the loop is to be continued by checking if obtained currentChar was enter.
if ((currentChar < '0' || currentChar > '9') && currentChar != '\b')
{
continue;
}
NOTE: You might want to read the comments on the else statement before you read these.
When the above if statement was false we get to the next if-statement (actually else if) that we see below.
As mentioned above: '\b' is backslash and if this is the user given char as well as string/array index being greater than 0 we move one character backwards in the console by "printing" '\b' and then write an empty character in order to delete what was written at that place previously. That puts us back to the position we were before so we print another backslash. At this point you might wonder why not just go back to the previous line that scanf_s causes, but that won't work. We must also not forget to replace the last string character with a null terminator and then set the index back by 1.
else if (currentChar == '\b')
{
if (index > 0)
{
// Delete last character
printf("\b \b");
readCharacters[index] = '\0';
--index;
}
}
When we hit this point we know that currentChar is something between 48 and 57 ('0' and '9').
_getch told the program what the user's input was, but we cannot see it in the console unless we print it there. So let's do that.
Also append the user's given character to the string as well as incrementing the index by 1.
else
{
printf("%c", currentChar);
readCharacters[index] = currentChar;
++index;
}
Lastly we call the atoi function that will convert our string/array to an integer.
int retVal = atoi(readCharacters);

Related

Output not showing in C

I'm writing a code that must identify the letter 't' or 'T' in a word, before or after the middle of it.
If the first half of the word does contain a 't' or a 'T', the program should output a 1. If the first half does not contain the letter 't' or 'T', but the second half does, then the program should output a 2. Otherwise, if there is no 't' or 'T' in the word at all, the program's output should be -1. The word entered will not have more than 50 letters.
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
t = word[i] == 't';
T = word[i] == 'T';
while(!t || !T) {
if((t || T) && i <= length / 2) {
printf("%d", '1');
} else if((t || T) && i > length / 2) {
printf("%d", '2');
//}else{
// printf("%d", '-1');
}
i++;
}
return 0;
}
If I enter any word and press enter, nothing is printed. Another thing is that when I remove the comment slashes from the two lines at the bottom, the program goes through an infinite loop.
Could someone please help?
This sounds like a school assignment, so I'll focus on advising/critiquing your code rather than giving a solution.
The first recommendation I have is to use a for loop instead of a while loop. A Rule of thumb in C is to only use a while loop when you actually don't have any idea how many things you need your program to look at.
You already have the length of the string, so set up your for loop to loop exactly once for each character.
Next you need to change how you are using printf. The %d format specifier is for printing integers, but you are passing it '1'. This is not an integer, it is the ascii representation of the symbol 1 (which is actually has the value 49, see the ascii table for more info)
You can either pass printf the value 1, or use the %c specifier, which expects ascii characters.
Better yet, just say printf("1");
That doesn't get you all the way there, but I think it lays the ground work so you can find the solution!
Condition !t || !T has no sense to be used as loop condition ...ask yourself how the loop will end ? you need just to check i is less than length
Second, the assignments t = word[i] == 't'; T = word[i] == 'T'; outside the loop have no sense ...you will be just pointing to the zero index of the string ...you should check all characters
third , the printf lines need to use %d
fourth , you appear not getting the purpose of the program printing inside loop will lead to printing many numbers and you just want to know if there is t or T you need to print single line.you may use variable int result=0; to hold the value you want and print it in the end ...of course you will need using break statement in the if((t || T) && i <= length / 2) and if((t || T) && i > length / 2) because no need for more searching
fifth, you should re-read , re-think , re-code the assignment before going bored and asking about it
sixth, there is a working version by modifying your code but you should try writing a good solution before looking at a solution as it better to solve your problems by yourself
#include <stdio.h>
#include <string.h>
int main() {
char word[50];
int i = 0, length, t = 0, T = 0;
scanf("%s", word);
length = strlen(word);
int result=0;
while( i<length) {
t = word[i] == 't';
T = word[i] == 'T';
if((t || T) && i <= length / 2) {
result=1;
break;
} else if((t || T) && i > length / 2) {
result=2;
break;
}else{
result=-1;
}
i++;
}
printf("%d",result);
return 0;
}
# include <stdio.h>
int main()
{
char name[20];
int age;
int siblings;
int childrens;
printf ("Hello my name is A.I, what is your name? \n");
scanf("%s", &name);
printf("how old are you : \n");
scanf("%d",&age);
printf("how many siblings you have: \n");
scanf("%d", &siblings);
printf("how many children you have: \n");
scanf("%d", &childrens);
printf("so your name is : %s \n", name);
printf("and your age is : %d \n", age);
printf("you have siblings : %d\n", siblings);
printf("so you have childrens : %d\n", childrens);
return 0;
}

Input of varying format in C

I am currently trying to figure out how to process an input of such format: [int_1,...,int_N] where N is any number from interval <1, MAX_N> (for example #define MAX_N 1000). What I have right now is fgets to get it as string which I then, using some loops and sscanf, save into an int array.
My solution is, IMO, not the most elegant and functional, but that's because of how I implement it. So what I'm asking I guess is how you guys would solve this problem, because I've ran out of ideas.
Edit: adding the code for string -> int array
int digit_arr[MAX_N];
char input[MAX_N];
//MAX_N is a constant set at 1000
//Brackets and spaces have been removed at this point
for (i = 0; i < strlen(input); i++) {
if(sscanf(&input[i+index_count],"%d,", &digit_arr[i]) == 1){
while (current_char != ',') {
current_char = input[i+index_count+j];
index_count++;
j++;
if ((index_count+j+i) == strlen(input)-1){
break;
}
}
}
My personal variant:
char const* data = input; // if input is NOT a pointer or you yet need it unchanged
for(;;)
{
int offset = 0;
if(sscanf(data, "%d,%n", digit_arr + i, &offset) == 1)
{
++i;
if(offset != 0)
{
data += offset;
continue;
}
}
break;
}
You might finally ckeck if all characters in the text are consumed:
if(*data)
{
// not all characters consumed, input most likely invalid
}
else
{
// we reached terminating null character -> fine
}
Note that my code as is does not cover trailing whitespace, you could do so by changing the format string to "%d, %n (note the added space character).

Putting numbers inside array at once in C

I'm struggling finding an answer to this: I want to be able to control if a credit card number (let's say '378282246310005') fulfills certain criteria (f.e. does it start with the number 3).
I want to be able to type the whole number at once, and then check certain places in the number (f.e. every second). However, I only managed to put them in an array when typing them one after another, which is annoying:
int main()
{
int user_input[5];
int i;
for(i=0;i<5;i++)
{
printf("Credit Card Number Digit %d\n",i+1);
scanf("%d",(user_input+i));
}
if(user_input[0] == 5)
printf("MASTERCARD\n");
else
printf("INVALID\n");
return 0;
}
Just check each digit as it is entered and ignore any non-numeric input, e.g.
int main()
{
int user_input[16];
int digits = 0;
while (digits < 16)
{
int c = getchar(); // get character
if (c == EOF) break; // break on EOF
if (isdigit(x)) // if character is numeric
{ // convert it to int and append to user_input array
user_input[digits++] = c - '0';
} // (otherwise just ignore it)
}
if (digits > 0 && user_input[0] == 5)
{
printf("MASTERCARD\n");
}
else
{
printf("INVALID\n");
}
return 0;
}
I would suggest scanning a string into an array of char and then access this array. The technique is included in this Wikipedia article, where the following code can be found.
#include <stdio.h>
int main()
{
char word[20];
if (scanf("%19s", word) == 1)
puts(word);
return 0;
}
The snipped reads a string in the array word, which can be accessed similar as in your question. Apparently, the maximum length of the string can be given as a parameter in the format string.

Detecting combination of characters from input

My task is:
Write a program that reads input up to # and reports the number of times that the sequence ei occurs.
I wrote something that in most of the times works, but there are inputs when it dosent...
Like this input:(suppose to return 1)
sdlksldksdlskd
sdlsklsdks
sldklsdkeisldksdlk
#
number of combination is: 0
This is the code:
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
char userInput;
char wordChar[index];
printf("please enter your input:\n");
while ((userInput = getchar()) != '#')
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
}
}
printf("number of combination is: %d", combinationTimes);
return 0;
}
Can you please tell me what am I not getting 1 using this input?
in the book he said to test it with "Receive your eieio award" and it worked...but after i played with it a little i see that not always.
It really doesn't seem necessary to read the file into an array. You just need to keep track of how many times ei is found before you read a # or reach EOF:
#include <stdio.h>
int main(void)
{
int c;
int ei_count = 0;
while ((c = getchar()) != EOF && c != '#')
{
if (c == 'e')
{
int c1 = getchar();
if (c1 == 'i')
ei_count++;
else if (c1 != EOF)
ungetc(c1, stdin);
}
}
printf("ei appeared %d times\n", ei_count);
return(0);
}
Testing (the program is called ei and is built from ei.c):
$ ei < ei.c
ei appeared 0 times
$ sed 1d ei.c | ei
ei appeared 1 times
$ sed 's/#/#/' ei.c | ei
ei appeared 4 times
$
The first one stops at the #include line, the second stops at the # in the comparison, and the third reads the entire file. It also gives the correct output for the sample data.
Analysing the code
Your primary problem is that you do not allocate any space for the array. Change the dimension of the array from index to, say, 4096. That'll be big enough for your testing purposes (but really the program should pay attention to the array and not overflowing it β€” but then I don't think the array is necessary at all; see the code above).
The next primary problem is that despite its name, getchar() returns an int, not a char. It can return any valid character plus a distinct value, EOF. So it must return a value that's bigger than a char. (One of two things happens if you use char. If char is a signed type, some valid character β€” often ΓΏ, y-umlaut, U+00FF, LATIN SMALL LETTER Y WITH DIAERESIS β€” is also treated as EOF even though it is just a character. If char is an unsigned type, then no input matches EOF. Neither is correct behaviour.)
Fixing that is easy, but your code does not detect EOF. Always handle EOF; the data may be malformatted. That's a simple fix in the code.
A tertiary problem is that the printf() statement does not end with a newline; it should.
Your test condition here is odd:
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
It's odd to use one pre-increment and one post-increment, but that's just a consistency issue.
Worse, though, is what happens when the character i appears in the input and is not preceded by e. Consider the line #include <stdio.h>: you start with index as 1; that is an i, so you decrement index, but wordChar[0] is not an e, so you don't increment it again, but the end of the loop does, so the loop checks index 1 again, and keeps on going around the loop testing that the i is i and # is not e for a long time.
There's no reason to decrement and then increment index; just use:
if (wordChar[index-1] == 'e')
combinationTimes++;
With those fixed, your code behaves. You trouble was largely that you were using an array that was not big enough (being size 0), and you were overwriting quasi-random memory with the data you were reading.
#include <stdio.h>
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
int userInput;
char wordChar[4096];
printf("please enter your input:\n");
while ((userInput = getchar()) != '#' && userInput != EOF)
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
printf("total: %d\n", total);
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[index-1] == 'e')
combinationTimes++;
}
}
printf("number of combination is: %d\n", combinationTimes);
return 0;
}
Note that you could reasonably write the nested if as:
if (wordChar[index] == 'i' && wordChar[index-1] == 'e')
combinationTimes++;
change your wordChar array value.
int main(void)
{
int index = 0;
int combinationTimes = 0;
int total = 0;
char userInput;
//char wordChar[index]; // index = 0
char wordChar[255]; // should change the value of array.
printf("please enter your input:\n");
while ((userInput = getchar()) != '#')
{
if (userInput == '\n')
continue;
wordChar[index] = userInput;
index++;
total++;
}
for (index = 1; index < total; index++)
{
if (wordChar[index] == 'i')
{
if (wordChar[--index] == 'e')
{
combinationTimes++;
++index;
}
}
}
printf("number of combination is: %d", combinationTimes);
return 0;
}
or maybe you can use pointer and then use malloc and realloc.

Putting numbers separated by a space into an array

I want to have a user enter numbers separated by a space and then store each value as an element of an array. Currently I have:
while ((c = getchar()) != '\n')
{
if (c != ' ')
arr[i++] = c - '0';
}
but, of course, this stores one digit per element.
If the user was to type:
10 567 92 3
I was wanting the value 10 to be stored in arr[0], and then 567 in arr[1] etc.
Should I be using scanf instead somehow?
There are several approaches, depending on how robust you want the code to be.
The most straightforward is to use scanf with the %d conversion specifier:
while (scanf("%d", &a[i++]) == 1)
/* empty loop */ ;
The %d conversion specifier tells scanf to skip over any leading whitespace and read up to the next non-digit character. The return value is the number of successful conversions and assignments. Since we're reading a single integer value, the return value should be 1 on success.
As written, this has a number of pitfalls. First, suppose your user enters more numbers than your array is sized to hold; if you're lucky you'll get an access violation immediately. If you're not, you'll wind up clobbering something important that will cause problems later (buffer overflows are a common malware exploit).
So you at least want to add code to make sure you don't go past the end of your array:
while (i < ARRAY_SIZE && scanf("%d", &a[i++]) == 1)
/* empty loop */;
Good so far. But now suppose your user fatfingers a non-numeric character in their input, like 12 3r5 67. As written, the loop will assign 12 to a[0], 3 to a[1], then it will see the r in the input stream, return 0 and exit without saving anything to a[2]. Here's where a subtle bug creeps in -- even though nothing gets assigned to a[2], the expression i++ still gets evaluated, so you'll think you assigned something to a[2] even though it contains a garbage value. So you might want to hold off on incrementing i until you know you had a successful read:
while (i < ARRAY_SIZE && scanf("%d", &a[i]) == 1)
i++;
Ideally, you'd like to reject 3r5 altogether. We can read the character immediately following the number and make sure it's whitespace; if it's not, we reject the input:
#include <ctype.h>
...
int tmp;
char follow;
int count;
...
while (i < ARRAY_SIZE && (count = scanf("%d%c", &tmp, &follow)) > 0)
{
if (count == 2 && isspace(follow) || count == 1)
{
a[i++] = tmp;
}
else
{
printf ("Bad character detected: %c\n", follow);
break;
}
}
If we get two successful conversions, we make sure follow is a whitespace character - if it isn't, we print an error and exit the loop. If we get 1 successful conversion, that means there were no characters following the input number (meaning we hit EOF after the numeric input).
Alternately, we can read each input value as text and use strtol to do the conversion, which also allows you to catch the same kind of problem (my preferred method):
#include <ctype.h>
#include <stdlib.h>
...
char buf[INT_DIGITS + 3]; // account for sign character, newline, and 0 terminator
...
while(i < ARRAY_SIZE && fgets(buf, sizeof buf, stdin) != NULL)
{
char *follow; // note that follow is a pointer to char in this case
int val = (int) strtol(buf, &follow, 10);
if (isspace(*follow) || *follow == 0)
{
a[i++] = val;
}
else
{
printf("%s is not a valid integer string; exiting...\n", buf);
break;
}
}
BUT WAIT THERE'S MORE!
Suppose your user is one of those twisted QA types who likes to throw obnoxious input at your code "just to see what happens" and enters a number like 123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 which is obviously too large to fit into any of the standard integer types. Believe it or not, scanf("%d", &val) will not yak on this, and will wind up storing something to val, but again it's an input you'd probably like to reject outright.
If you only allow one value per line, this becomes relatively easy to guard against; fgets will store a newline character in the target buffer if there's room, so if we don't see a newline character in the input buffer then the user typed something that's longer than we're prepared to handle:
#include <string.h>
...
while (i < ARRAY_SIZE && fgets(buf, sizeof buf, stdin) != NULL)
{
char *newline = strchr(buf, '\n');
if (!newline)
{
printf("Input value too long\n");
/**
* Read until we see a newline or EOF to clear out the input stream
*/
while (!newline && fgets(buf, sizeof buf, stdin) != NULL)
newline = strchr(buf, '\n');
break;
}
...
}
If you want to allow multiple values per line such as '10 20 30', then this gets a bit harder. We could go back to reading individual characters from the input, and doing a sanity check on each (warning, untested):
...
while (i < ARRAY_SIZE)
{
size_t j = 0;
int c;
while (j < sizeof buf - 1 && (c = getchar()) != EOF) && isdigit(c))
buf[j++] = c;
buf[j] = 0;
if (isdigit(c))
{
printf("Input too long to handle\n");
while ((c = getchar()) != EOF && c != '\n') // clear out input stream
/* empty loop */ ;
break;
}
else if (!isspace(c))
{
if (isgraph(c)
printf("Non-digit character %c seen in numeric input\n", c);
else
printf("Non-digit character %o seen in numeric input\n", c);
while ((c = getchar()) != EOF && c != '\n') // clear out input stream
/* empty loop */ ;
break;
}
else
a[i++] = (int) strtol(buffer, NULL, 10); // no need for follow pointer,
// since we've already checked
// for non-digit characters.
}
Welcome to the wonderfully whacked-up world of interactive input in C.
Small change to your code: only increment i when you read the space:
while ((c = getchar()) != '\n')
{
if (c != ' ')
arr[i] = arr[i] * 10 + c - '0';
else
i++;
}
Of course, it's better to use scanf:
while (scanf("%d", &a[i++]) == 1);
providing that you have enough space in the array. Also, be careful that the while above ends with ;, everything is done inside the loop condition.
As a matter of fact, every return value should be checked.
scanf returns the number of items successfully scanned.
Give this code a try:
#include <stdio.h>
int main()
{
int arr[500];
int i = 0;
int sc = 0; //scanned items
int n = 3; // no of integers to be scanned from the single line in stdin
while( sc<n )
{
sc += scanf("%d",&arr[i++]);
}
}

Resources