Partitioning inputs in scanf - c

I want to accept the string and the float value in between the '#' is present. I have tried some what like this but it's not working; it is taking the whole input as the string.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[10000];
float number;
scanf("%s#%f",str,&number); //input BMW#23.5 Expected output BMW 23.5
printf("%s %f\n",str,number); //actual output BMW#23.5 0.000000
}
Can anyone help me to solve this?

Get all as a char[] and parse it:
int main()
{
char str[10000];
float number;
scanf("%s", str);
char *at_pos = strrchr(str, '#');
if (at_pos)
{
number = atof(at_pos + 1);
// manage errors in number
printf("%s %f\n", str, number);
}
else
{
// manage error
}
}

//using the "[^#]" can really save your time.
//But you can do a lot in this approach of mine. Not just in that case.
//Feel free to ignore this but if you want to check and understand the logic there, there's the code that i wrote. Then you can just improve it. Tnx.
#include <stdio.h>
int main(void)
{
char str[10000];
char c;//The idea is, collect the input 1 by 1.
float f;
float power = 10;
int counter = 0;//We need this for the string.
c = getchar();//get the first character
str[counter] = c;//store it in the first element
counter++;
c = getchar();//Since we know that the input is string, we assume that there's a next character of course.
while(c != '#')
{
//But what if the user didn't enter a '#' character?
//Do this!
if(c == 10)
{
printf("I can't find the '#' there. =)\n\n");
return 0;
}
str[counter++] = c; //Test the recently collected character if
c = getchar(); //it's '#' or not. If not, then store it
} //in the string and continue to collect the
//next characters then store each of it in
//the string again and again until it reaches the '#'. From there you stop.
//after collecting all the characters, start collecting the numbers.
c = getchar();//collect
f = c - '0';//convert character to digit. I would bet you know this. Then store it in your float variable.
c = getchar();//collect again
//then test the recently collected again. Just like before
while(c != 10 && c != '.')//10 is the ASCII of the <enter> or new line right?. //We will also stop if we encounter '.' (dot)..
{
//while if it's not 10 or dot, add it your float variable. But don't forget the rules. use the power of 10 to.
f = f * 10 + (c - '0');
c = getchar();//collect again.
}
//do this again
c = getchar();
f += (c - '0') / power;//now divide it with power
c = getchar();
power *= 10;//then increase the power.
//Now collect the decimals
while(c != 10)//just like before
{
f += (c - '0') / power; //just do this over and
power *= 10; //over again until
c = getchar(); //it reaches the ASCII 10.
}
//Test it if you got it. =)
printf("%s # %f", str, f);
return 0;
}
//here's the clean code.
#include <stdio.h>
int main(void)
{
char str[1000];
char c;
float f;
float power = 10;
int counter = 0;
c = getchar();
str[counter] = c;
counter++;
c = getchar();
while(c != '#')
{
//But what if the user didn't enter a '#' character?
//Do this!
if(c == 10)
{
printf("I can't find the '#' there. =)\n\n");
return 0;
}
str[counter++] = c;
c = getchar();
}
c = getchar();
f = c - '0';
c = getchar();
while(c != 10 && c != '.')
{
f = f * 10 + (c - '0');
c = getchar();
}
c = getchar();
f += (c - '0') / power;
c = getchar();
power *= 10;
while(c != 10)
{
f += (c - '0') / power;
power *= 10;
c = getchar();
}
printf("%s # %f", str, f);
return 0;
}

Related

if/else not receiving value at array in C [duplicate]

#include<stdio.h>
#include<ctype.h>
int peekchar() {
int c;
c = getchar();
if (c != EOF) {
ungetc(c, stdin);
}
return c;
}
int readNumber(void) {
int c;
int accumulator = 0;
while ((c = peekchar() != EOF) && isdigit(c)) {
c = getchar();
accumulator *= 10;
accumulator += c - '0';
}
return accumulator;
}
int main() {
int result = readNumber();
printf("%d\n", result);
return 0;
}
I am trying to read an integer written in decimal notation from stdin until the first non-digit. But its not giving the correct result:
M1508444:CProg sb054043$ gcc -g3 readNumber.c -o readNumber
M1508444:CProg sb054043$ ./readNumber
123
0
Can someone please help me identify the problem?
The issue is with operator precedence. c = peekchar() != EOF is grouped as c = (peekchar() != EOF), and so c is either 0 or 1, which accounts for the result.
Fix with (c = peekchar()) != EOF.
Or, given that isdigit is defined to be 0 for EOF, your loop conditional can be simplified to
while (isdigit(c = peekchar())){
Hi you need to modify your while loop like below:-
while ( (c = peekchar()) != EOF && isdigit(c)) {
c = getchar();
accumulator *= 10;
accumulator += c - '0';
}
First of all you need to read the value and store it in variable c and that you can achieve by doing (c = peekchar()). Once the value stored in c now your while loop will first check whether it is EOF if not then only it will check whether it is a digit or not.

Reading float numbers using getchar() and printing the float number and it's double

I'm having trouble in converting numbers to float using getchar() method to solve my problem. For my problem I need to store characters in an array of fixed size = 50. Also, storing in an array only happens when there is a space ' ' or a newline \n read using getchar(). This happens until EOF is read. At last, the float number and it's double (with a tab space) is returned and printed using printf.
As per instructions, only getchar() is allowed. Functions like scanf(), fgets(), atoi(), atol(), atof(), strtol(), strtoul() or an extra array can not be used.
Here is what I've come up with till now. ( see sample input and output at bottom )
#include <stdio.h>
#define SIZE 50 // assume no more than 50 literals in input
int main(){
float c;
float u;
float value = 0.0;
float resu[SIZE];
int index = 0;
int i;
char sub = '0';
value = 0;
c = getchar();
while ( c != EOF){
if(c == '.'){
u = 0.1;
}
else if (c == ' ' || c == '\n'){
if(u == 0.1){
value = value * 0.1;
}
resu[index] = value;
index++;
value = 0;
}
if( c >= '0' && c <= '9'){
value = value * 10 + (c-sub);
}
c = getchar(); // read next
}
//printing the result
for(i=0; i < index; i++)
printf("%.4lf \t %.4lf\n", resu[i],resu[i] *2.0);
return 0;
}
(Note- There is a tab between the original number and it's double)
Sample Input:
2.3 4.56
43.3 43 5.3
.3 1.2
Sample Output:
2.3000 4.6000
45.6000 91.2000 //ERROR
43.3000 86.6000
4.3000 8.6000 //ERROR
5.3000 10.6000
0.3000 0.6000
1.2000 2.4000
Two things you don't do is initialize u or reset u for each word.
float u = 0;
....
else if (c == ' ' || c == '\n') {
if (u == 0.1){
value = value * 0.1;
}
resu[index] = value;
index++;
value = 0;
u = 0; // Reset it for next number
}
Also, you hard-code u = 0.1, but that only works when there is only 1 decimal place. That may be ok for this assignment, but a better option would be to count the digits after the decimal.
#include <stdbool.h>
#include <math.h>
#include <ctype.h>
...
int digits_after_decimal = 0;
bool have_decimal_point = false;
int value = 0;
int c;
while ((c = getchar()) != EOF) {
// Decimal point found?
if ('.' == c) {
have_decimal_point = true;
}
else if (isdigit(c)) {
// Add this digit to integer value
// Parentheses not required but added for clarity
value = (value * 10) + (c - '0');
// If decimal point already found, increment count
if (have_decimal_point) digits_after_decimal += 1;
}
// Complete word. Save and reset
// TODO: Multiple spaces between words?
else if (' ' == c || '\n' == c) {
// Divide by the correct power of 10 based on
// the number of digits after the decimal point
resu[index++] = value / pow(10, digits_after_decimal);
if (index == SIZE) break; // Avoid overflow
// Reset for next number
digits_after_decimal = 0;
have_decimal_point = false;
value = 0;
}
// TODO: Negative numbers?
}

C Program doesn't end after giving the correct output

So I'm trying to do a program that reads a sequence of numbers separated by spaces and new lines. The output should be the same sequence, but erasing unnecessary zeros(The sequence of charachters 'EOF' ends the program). Per example
01492 102934 should come out as 1492 102934
9312 0 01923 should come out as 9312 0 1923
0001249 0000 should come out as 1249 0
Well I've achieved that purpose but have come across a roadblock. The program doesn't exit unless I type the EOF sequence. Maybe it's because I have a while(1) running that gives an infinite loop. But when I try to delete it the program doesn't even print at all. I'm still learning this is for a school project.
Any help would be apreciated!
Here's the code:
#include <stdio.h>
int main(){
char c;
int i=0;
while(1){
c=getchar();
if (i==0){
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
i=i+1;
}
else if (c==' '){
printf("%c",c);
c=getchar();
if(c=='0'){
while (c=='0'){
c=getchar();
}
}
printf("%c",c);
}
else if (c=='E'){
c=getchar();
if (c=='O'){
c=getchar();
if(c=='F'){
printf("\n");
return 0;
}
}
}
else{
printf("%c",c);
}
}
}
The important stuff:
int c; // IMPORTANT, cannot be char
while (1) {
c = getchar();
if (c == EOF) break; // exit loop
// ...
}
There has to be some way to tell the program to exit.
With this, the program will exit on the letter x or two consecutive newlines or entering END.
getchar will return EOF when there is nothing left to read from a file. That can be simulated from stdin ( the keyboard) with ctrl + z on Windows or ctrl + d on Linux.
#include <stdio.h>
#include <string.h>
int main ( void) {
char done[4] = "";
int c = 0;
int prior = 0;
int reading = 0;
int zero = 1;
while ( EOF != ( c = getchar ( )) && 'x' != c) {
if ( '\n' == c && '\n' == prior) {
break;
}
if ( c >= '0' && c <= '9') {
reading = 1;
if ( '0' != c) {
zero = 0;
}
if ( ! zero) {
putchar ( c);
}
}
else {
if ( reading) {
if ( zero) {
putchar ( '0');
}
if ( ' ' == c || '\n' == c) {
putchar ( c);
}
else {
putchar ( ' ');
}
}
reading = 0;
zero = 1;
}
prior = c;
done[0] = done[1];
done[1] = done[2];
done[2] = c;
done[3] = 0;
if ( 0 == strcmp ( done, "END")) {
break;
}
}
putchar ( '\n');
return 0;
}
getchar() returns an int, not a char. If it only returned a char, there would be no way for it to return a value that indicates end of file, since all char values are valid and can’t be used for another purpose.
A motivating example in decimal system may be: A function checks the temperature returns a two-digit number. Any temperature between 0 and 99 is valid. How do you report errors when the thermometer is disconnected? You have to return a number with more digits, and use a special value like UNPLUGGED = 100.
But int is a wider type: it has many more values than char, and the “extra” values can be used to indicate some special condition that means “hey, this is not a valid character, but something else I had to tell you”.
getchar() returns the EOF constant upon failure (any failure), for example if no more input is available. There’s nothing sensible you can do even if the reason for the failure other than end of input. You should end processing at the first EOF.
Thus, change the type of c to int, and every time you call getchar(), you must check that its value is not EOF, and return when you encounter it.
The nested structure of your loops means that EOF checking has to be repeated all over the place. There are other ways to structure the code to keep this check in one place, but, admittedly, the nested loops have at least the potential to exploit the branch predictor, whereas a single getchar followed by a state-machine style switch statement will make it perform potentially worse. None of this matters in a simple homework problem, but it’s something to keep in mind. In any case, performance has to be benchmarked - no other way around it.
Try this code, I think it does what you requested:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
static int getLine(char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf("%s", prmpt);
fflush(stdout);
}
if (fgets(buff, sz, stdin) == NULL)
return -2;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff) - 1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? -1 : 0;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff) - 1] = '\0';
return 0;
}
int* convert2numbers(char* arr, int size) {
int i;
int j;
int k;
char token[100];
int* numbers;
int last_space = 0;
int index = 1;
int amount = 1;
// Count the amount of tokens.
for (i = 0; i < size; ++i) {
if (arr[i] == ' ') {
++amount;
}
}
numbers = (int *)malloc(amount * sizeof(int));
numbers[0] = amount;
for (j = 0; j <= size; ++j) {
if (arr[j] == ' ' || arr[j] == '\0') {
// Copy token from input string.
for (k = 0; k < j; ++k) {
token[k] = arr[k + last_space];
}
token[j] = '\0';
numbers[index] = atoi(token);
// Clear the token and continue.
memset(token, '\0', sizeof(token));
last_space = j;
++index;
}
}
return numbers;
}
int main(void) {
int i;
int size;
int* numbers;
int amount;
char input[100];
char help[] = "Numbers> ";
printf("Input numbers below or press enter to exit!\n");
while (1) {
getLine(help, input, sizeof(input));
// If input is empty exit.
if (input[0] == '\0') {
break;
}
size = strlen(input);
numbers = convert2numbers(input, size);
amount = numbers[0];
for (i = 1; i < amount + 1; ++i) {
printf("%d ", numbers[i]);
}
printf("\n");
}
return 0;
}
When run with these inputs this code outputs:
Input numbers below or press enter to exit!
Numbers> 01492 102934
1492 102934
Numbers> 9312 0 01923
9312 0 1923
Numbers> 0001249 0000
1249 0
Also if you press enter in console, it exits, as to escape the while(1) loop, easily.

C Program to read number character by character giving incorrect result

#include<stdio.h>
#include<ctype.h>
int peekchar() {
int c;
c = getchar();
if (c != EOF) {
ungetc(c, stdin);
}
return c;
}
int readNumber(void) {
int c;
int accumulator = 0;
while ((c = peekchar() != EOF) && isdigit(c)) {
c = getchar();
accumulator *= 10;
accumulator += c - '0';
}
return accumulator;
}
int main() {
int result = readNumber();
printf("%d\n", result);
return 0;
}
I am trying to read an integer written in decimal notation from stdin until the first non-digit. But its not giving the correct result:
M1508444:CProg sb054043$ gcc -g3 readNumber.c -o readNumber
M1508444:CProg sb054043$ ./readNumber
123
0
Can someone please help me identify the problem?
The issue is with operator precedence. c = peekchar() != EOF is grouped as c = (peekchar() != EOF), and so c is either 0 or 1, which accounts for the result.
Fix with (c = peekchar()) != EOF.
Or, given that isdigit is defined to be 0 for EOF, your loop conditional can be simplified to
while (isdigit(c = peekchar())){
Hi you need to modify your while loop like below:-
while ( (c = peekchar()) != EOF && isdigit(c)) {
c = getchar();
accumulator *= 10;
accumulator += c - '0';
}
First of all you need to read the value and store it in variable c and that you can achieve by doing (c = peekchar()). Once the value stored in c now your while loop will first check whether it is EOF if not then only it will check whether it is a digit or not.

Performing arithmetic on Characters in C

I am trying to write a program that adds, subtracts, multiplies, and divides a string of characters. Where I'm at now with the program is figuring out how to split the input string into two strings, and then perform the appropriate +-/*.
The input should look like this abc+aaa
and the output for that should be abc + aaa = bcd
How do I convert character strings into integer strings?
#include <stdio.h>
#include <math.h>
#include <string.h>
int main() {
printf("This is a pseudo arithmetic program");
char input[10];
input[10] = '\0';
char first [9];
first[9] = '\0';
char last [9];
last[9] = '\0';
int i = 0;
int b;
int e;
while (input[0] != '0') {
if (input[0] == 0){
return -1;
}
printf("\nEnter a math problem in SOS format using only lowercase letters up to 9 characters");
printf("\nEx: abc+abc... type '0' to quit \n");
scanf("%s", input);
int x = 0;
x = strlen(input);
if (strchr(input, '+')){
for (i = 0; i <= x; i++) {
if (i == '+')
strncpy(first, &input[0], i-1);
i = 0;
}
for (i = x; i >= input[0]; i--) {
if (i == '+')
strncpy(last, &input[i], x);
i = 0;
}
printf("%s", first);
printf(" + ");
printf("%s", last);
printf(" = %d", first + last);
}
There seems to be multiple problems with your code:
There is a array out of bounds happening for almost all the arrays:
char input[10];
input[10] = '\0';
In this if you want to initialize the last character with '\0' then it should be
input [9] = '\0'
Arrays indexes always start from 0.
It is not clear what is the use of below lines:
while (input[0] != '0') { if (input[0] == 0){ return -1; }
When taking input for a string, why are prompting users to enter a 0 to end it?
strrchr returns the pointer from where the searched character begins. So, you can that itself to determine where the '+' symbol is and two split the strings instead of your while loop. See strrchr man page
Also, your idea of adding characters is not clear. From your example, it appears you are considering a = 1, b = 2 etc. In such a case, if your code is case insensitive, then you can convert all your input to upper case and then do (input[0] - 'A')+1 to convert your letters like a, b, c to 1, 2, 3 etc.
Hope these pointers help. Suggest you check your problem statement again and refactor your code accordingly.

Resources