# Thread: Maximum of the real numbers found into the input

1. ## Maximum of the real numbers found into the input

Write a function that reads data from standard input until EOF is found and returns the maximum of the real numbers found into the input.
We consider a real number as a number composed of two numbers in base-10, joined by a comma.
The numbers must be separated from other words by at least one whitespace.
All the numbers are guaranteed to be positive and to fit in "unsigned" and "double" data types.
Code:
```#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX 100
unsigned checkWord(char *word)
{
int i, j=0,k=0, comma, len = strlen(word);
char firstHalf[MAX], secondHalf[MAX];
if(!isdigit(word) || !isdigit(word[len-1]))
return 0;
for(i = 1; i < len-1; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = 1; i < comma; i++)
{
if(!isdigit(word[i]))
return 0;
}
for(i = comma+1; i < len-1; i++)
{
if(!isdigit(word[i]))
return 0;
}
}
}
return 1;
}
float maximum(float a, float b)
{
if(a > b)
return a;
else
return b;
}
char *firstHalfNumber(char *word)
{
int i, j=0, comma, len = strlen(word);
char firstHalf[MAX];
for(i = 1; i < len-1; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = 1; i < comma; i++)
{
firstHalf[j++] = word[i];
}
}
}
}
char *secondHalfNumber(char *word)
{
int i, k=0, comma, len = strlen(word);
char secondHalf[MAX];
for(i = 1; i < len-1; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = comma+1; i < len-1; i++)
{
secondHalf[k++] = word[i];
}
}
}
}
int main()
{
char s[MAX];
float a, b;
float maxi;
while(fgets(s, MAX, stdin))
{
s[strlen(s)-1] = '\0';
char *word = strtok(s, " ");
while(word != NULL)
{
//printf("word: %s\n", word);
if(checkWord(word) == 1)
{
a = atoi(firstHalfNumber(word));
b = atoi(secondHalfNumber(word));
maxi = maximum(a, b);
}
}
}
printf("The maximum is %lf.\n", maxi);
return 0;
}```

So my idea was to break each line into words, check if the word is a number and then separately break each number into firstHalf(until the comma) and secondHalf(after comma), then use atoi on each and compare them. But I made a lot of mistakes and I'm getting segmentation fault when running the program. Could you give me some ideas? 2. You need to maximize the warning level of your compiler, pay attention to the warnings, and fix them. You have four unused variables in checkWord and you don't return anything from firstHalfNumber or secondHalfNumber functions. If you want to "return" the local char arrays then you will need to make them static.

you need a second call to strtok at the end in the inner while loop in main in order to move on to the next number. Remember in that call that s needs to be replaced with NULL.

I don't see why you start your loop at 1 and go up to < len - 1 in the "half" functions. You'll miss the first and last digits.

I don't see why you are looking for the maximum of the two halves. Aren't they two parts of the same real number? I'm assuming that the comma is being used for the same purpose as the period for Americans, to separate the two parts of a single real number.

I can think of some other potential problems, but that should be enough to get you going. 3. Instead of parsing the number yourself, I wonder if it will be easier to "cheat" by replacing the comma, if one exists, with a period, then calling something like strtod. 4. Originally Posted by laserlight Instead of parsing the number yourself, I wonder if it will be easier to "cheat" by replacing the comma, if one exists, with a period, then calling something like strtod.
Haha, that's actually what I wanted to do so I would spare myself of all the work but I thought I'd solve it the way it was stated first 5. Originally Posted by john.c You need to maximize the warning level of your compiler, pay attention to the warnings, and fix them. You have four unused variables in checkWord and you don't return anything from firstHalfNumber or secondHalfNumber functions. If you want to "return" the local char arrays then you will need to make them static.
Okay I have no more warnings:
Code:
```#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX 100
unsigned checkWord(char *word)
{
int i, comma, len = strlen(word);
if(!isdigit(word) || !isdigit(word[len-1]))
return 0;
for(i = 1; i < len-1; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = 1; i < comma; i++)
{
if(!isdigit(word[i]))
return 0;
}
for(i = comma+1; i < len-1; i++)
{
if(!isdigit(word[i]))
return 0;
}
}
}
return 1;
}
float maximum(float a,float b)
{
if(a > b)
return a;
else
return b;
}
char *firstHalfNumber(char *word)
{
int i, j=0, comma, len = strlen(word);
char *firstHalf = calloc(MAX, sizeof(char));
for(i = 0; i < len; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = 1; i < comma; i++)
{
firstHalf[j++] = word[i];
}
}
}
free(firstHalf);
return firstHalf;
}
char *secondHalfNumber(char *word)
{
int i, k=0, comma, len = strlen(word);
char *secondHalf = calloc(MAX, sizeof(char));
for(i = 0; i < len; i++)
{
if(word[i] == ',')
{
comma = i;
for(i = comma+1; i < len-1; i++)
{
secondHalf[k++] = word[i];
}
}
}
free(secondHalf);
return secondHalf;
}
int main()
{
char s[MAX];
float a, b;
float maxi;
while(fgets(s, MAX, stdin))
{
s[strlen(s)-1] = '\0';
char *word = strtok(s, " ");
while(word != NULL)
{
//printf("word: %s\n", word);
if(checkWord(word) == 1)
{
// a = atoi(firstHalfNumber(word));
// b = atoi(secondHalfNumber(word));
// maxi = maximum(a, b);
}
word = strtok(NULL, " ");
}
}
printf("The maximum is %lf.\n", maxi);
return 0;
}```
I don't see why you are looking for the maximum of the two halves. Aren't they two parts of the same real number? I'm assuming that the comma is being used for the same purpose as the period for Americans, to separate the two parts of a single real number.
I'm not, I realised I called the maximum function to check the max of the two halves, but that's not my intention. What I wanna do is: compare the first halves of the first 2 floats, if they are equal also compare the second halves, if they're also equal the numbers are equal and I compare the next one and so on. 6. Wouldn't it be possible to set the locale to a country that uses the comma as decimal separator and read the input as a flaot ? 7. Two problems. It makes your program dependent on the user having that locale on their system. Also, using something like sscanf("%f",...) or strtod will allow a value without a fractional part (which seems to be against your directions) as well as forms like 1,2e3.
Code:
```#include <stdio.h>
#include <string.h>
#include <locale.h>

int main() {
if (!setlocale(LC_NUMERIC, "en_DK.utf8")) {
printf("setlocale failed\n");
return 1;
}

char line;
const char *const Seps = " \t\r\n";

while (fgets(line, sizeof line, stdin)) {
char *tok = strtok(line, Seps);
while (tok) {
double f;
int n;
if (sscanf(tok, "%lf%n", &f, &n) == 1 && !tok[n])
printf("%f\n", f);
tok = strtok(NULL, Seps);
}
}

return 0;
}```
EDIT: The second problem can be solved with an additional test.
Code:
```#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>

int okay(const char *s) {
int commas = 0;
for (const char *p = s; *p; ++p)
if (*p == ',') {
// error if more than 1 comma or it's first or last char
if (++commas > 1 || p == s || !p)
return 0;
}
else if (!isdigit(*p))
return 0;
return 1;
}

int main() {
if (!setlocale(LC_NUMERIC, "en_DK.utf8")) {
printf("setlocale failed\n");
return 1;
}

char line;
const char *const Seps = " \t\r\n";

while (fgets(line, sizeof line, stdin)) {
char *tok = strtok(line, Seps);
while (tok) {
double f;
if (okay(tok) && sscanf(tok, "%lf", &f) == 1)
printf("%f\n", f);
tok = strtok(NULL, Seps);
}
}

return 0;
}``` 8. Can you use sscanf to split each "word" in a line into numbers?

Code:
```double a, b;
char *word = line;
int n, offset;
while ((n = sscanf(word, "%lf,%lf%n", &a, &b, &offset)) == 2) {
word += offset;
// do something with a and b
}```
Edit: on second thought, there's no need to use both fgets and sscanf. You can use scanf by itself (and you don't need "offset" and %n in the format string) to do the same thing. 9. @christop, I think the input is a mixture of words and numbers, e.g.:
Code:
`alpha beta 3,14 gamma 145,70 delta epsilon 0012,34 zeta`
Your variable n is unused in your code.

There's no reason to use double (in fact it's wrong since it would allow 1.2,3.4). Use unsigned int instead. Although a problem with an input spec like "%u,%u" is that it would allow "1, 2" since %u skips whitespace first.

The assignment can be done with only unsigned ints, avoiding floating point entirely.

Here's the original assignment description:
Write a function that reads data from standard input until EOF is found and returns the maximum of the real numbers found in the input. We consider a real number as a number composed of two numbers in base-10, joined by a comma. The numbers must be separated from other words by at least one whitespace. All the numbers are guaranteed to be positive and to fit in "unsigned" and "double" data types.
E.g. of valid numbers: 3,14 145,70 0012,34 etc. 10. Originally Posted by thmm Wouldn't it be possible to set the locale to a country that uses the comma as decimal separator and read the input as a flaot ?
I'm kind of a newbie in C and I haven't learned about setlocale yet 11. Originally Posted by john.c @christop, I think the input is a mixture of words and numbers, e.g.:
Code:
`alpha beta 3,14 gamma 145,70 delta epsilon 0012,34 zeta`
Ah, I read the description as if a comma-separated pair of numbers was called a "word". I suppose the assignment could be intended to have actual words on the input as you described. That definitely is more challenging than my simple approach (but if I were the OP I'd ask the instructor for clarification on this point). 12. Wouldn't it be possible to set the locale to a country that uses the comma as decimal separator and read the input as a flaot ?
Two problems. It makes your program dependent on the user having that locale on their system. Also, using something like sscanf("%f",...) or strtod will allow a value without a fractional part (which seems to be against your directions) as well as forms like 1,2e3.
You are right. Thanks for pointing it out. 13. @christop, You're right that the word "word" is ambiguous. I just assumed it had it's "normal" meaning, but it could just mean "token" and the input could just be all numbers of the given form. I was also assuming that their could be numbers in the wrong form: starting or ending with a comma, having no comma or more than one comma, etc. But who knows. 14. It sounds like this is the problem text rather than a paraphrase: "The numbers must be separated from other words by at least one whitespace."

If so, "word" in this context is used to mean "token", but the fact that "number" is also used seems to imply that there are "words" that are not "numbers". Otherwise, it'll make more sense to just stick to "number" as used in the preceding text. Popular pages Recent additions #### Tags for this Thread

char, comma, fori, i++, return 