1

I need to read an integer one by one until i read a '$', and then to determine the largest, smallest and so on. I could use a character variable and do it, but it works for numbers from 0 to 9. But how do I read integers of two or more digits and at the same time, detect a '$' - I used a char *, but I guess it is equivalent to an array, which I should not use here. Also, char holds a single number / char, hence not suitable for larger numbers. What should I do?

5
  • 1
    C or C++ pick one, and if it is homework mark it as so. Commented Oct 5, 2011 at 13:17
  • from what will you read? Commented Oct 5, 2011 at 13:17
  • "I could use a character variable and do it, but it works for numbers from 0 to 9" What makes you think that? Commented Oct 5, 2011 at 13:19
  • @jrok The OP probably meant that using char you can only read one digit at a time. Commented Oct 5, 2011 at 13:19
  • @Joe: It is C, and it isn't a homework. I can use the same for numbers from 0-9, but not for the higher ones. Commented Oct 5, 2011 at 13:22

6 Answers 6

2

No arrays, no pointers, no tricky char-by-char read & convert. Just plain scanf and getchar.

#include <stdio.h>

int main()
{
    int newValue=0;        /* value being acquired */
    int max;               /* current maximum value */
    int min;               /* current minimum value */
    int firstAcquired=0;   /* boolean flag set to 1 after first acquisition */
    int ch;                /* used as temporary storage for the getchar() */
    for(;;)
    {
        /* scanf returns the number of successfully acquired fields; here if it
           returns 0 means that the value couldn't be acquired */
        if(scanf("%d",&newValue)==0)
        {
            /* scanf failed, but it's guaranteed it put the offending character
               back into the stream, from where we can get it */
            ch=getchar();
            if(ch=='$' || ch==EOF)
                break;
            else
            /* from here to the break it's just to handle invalid input and EOF
               gracefully; if you are not interested you can replace this stuff
               with a random curse to the user */
            {
                puts("Invalid input, retry.");
                /* Empty the buffer */
                while((ch=getchar())!='\n' && ch!=EOF)
                    ;
            }
            /* if it's EOF we exit */
            if(ch==EOF)
                break;
        }
        else
        {
        /* Everything went better than expected */
            if(!firstAcquired || newValue>max)
                max=newValue;
            if(!firstAcquired || newValue<min)
                min=newValue;
            firstAcquired=1;
        }
    }
    if(firstAcquired)
    {
        printf("The maximum value was %d\n", max);
        printf("The minimum value was %d\n", min);
    }
    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

1

In the interest of spoiling all the fun, showing off, outright overkill and darn tooting fun:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
namespace qi = boost::spirit::qi;

template <typename V>
void show_statistics(const V& data)
{
    using namespace boost::spirit::karma;
    std::cout << "data:\t"<< format('{' << auto_ % ", " << '}', data) << std::endl;

    std::cout << "min:\t" << *std::min_element(data.begin(), data.end()) << std::endl;
    std::cout << "max:\t" << *std::max_element(data.begin(), data.end()) << std::endl;

    auto sum = std::accumulate(data.begin(), data.end(), 0);
    std::cout << "sum:\t" << sum << std::endl;
    std::cout << "avg:\t" << (1.0*sum) / data.size() << std::endl;
}

void dostats(const std::vector<int>& data) { show_statistics(data); }

int main()
{
    std::cin.unsetf(std::ios::skipws);
    auto f = boost::spirit::istream_iterator(std::cin);
    decltype(f) l;

    bool ok = qi::phrase_parse(f, l, +(+qi::int_ > "$") [ dostats ], qi::space);

    if (f!=l)
        std::cout << "Remaining input unparsed: " << std::string(f,l) << std::endl;

    return ok? 0:255;
}

Demo:

Sample run:

sehe@natty:/tmp$ ./test2 <<< "1 2 3 4 5 $ 3 -9 0 0 0 $ 900 9000 $ unparsed trailing text"
data:   {1, 2, 3, 4, 5}
min:    1
max:    5
sum:    15
avg:    3
data:   {3, -9, 0, 0, 0}
min:    -9
max:    3
sum:    -6
avg:    -1.2
data:   {900, 9000}
min:    900
max:    9000
sum:    9900
avg:    4950
Remaining input unparsed: unparsed trailing text

1 Comment

@MatteoItalia: Thx; well, only after prodding. and, ah, who cares :). it is good exercise, and should be quite educational / entertaining to read if there is anyone with the same curiosities as myself
0

You can use 'scanf("%s")' to read a group of characters. You can then check if the first character is a '%' and terminate if so. Otherwise, call atoi to convert to an integer. Store the largest and smallest in integer types, not character types.

Basically, the only time you have to deal with characters is when you read them in and check if it's a '$'. Otherwise, use integers all the way through.

16 Comments

Have used atoi.... but in order to use %s, the declaration must be of the type: char varName[10];, isn't it?
No. It can just as well be char *s; s=malloc(256);.
Isn't the name of an array the same as a pointer to the first element in an array?
@user980411: It depends what you mean by array. Since the stack is an array of bytes, if you "can't use an array", you can't call any functions.
@David Schwartz: I should not call functions too.
|
0

If I'm getting what you want correctly it should be something like this:

int i = 0;
char c = getchar();
while (c != '$')
{
    i = i * 10 + (c - '0');
    c = getchar();
}

Hope it helped.

1 Comment

See question comments, it's C.
0

You can read char by char in a loop, check values and so on...

int i = 0;
char c = 0;
int size = 10;
int currentIndex = 0;
int* integers = malloc(sizeof(int) * size);
int counter = 0;
do
{
    scanf("%c", &c);
    if (c == ' ') // Match space, used a number separator
    {
        if (counter != 0 && i != 0)
        {
            if (currentIndex >= size)
            {
                size += 5;
                integers = realloc(integers, size);
            }
            integers[currentIndex] = i;
            currentIndex++;
        }
        counter = 0;
        i = 0;
    }
    else if (c >= '0' && c <= '9')
    {
        i = (i * counter * 10) + (c - '0');
        counter++;
    }
}
while(c != '$');

Don't forget to free integers in the end!

1 Comment

OP said it's C. (see question comments)
0
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define BUFF_SIZE 16
#define DATA_MAX_SIZE 64

int main(){
    char buff[BUFF_SIZE];
    int data[DATA_MAX_SIZE];
    int i,value,counter = 0;
    char *buffp,*p;
    while(NULL!=fgets(buff,BUFF_SIZE,stdin)){
        buff[BUFF_SIZE - 1]='\0';
        buffp = buff;
next:   while(isspace(*buffp))
            ++buffp;
        if(*buffp == '\0')
            continue;
        value = strtol(buffp, &p, 0);
        if(counter == DATA_MAX_SIZE){
            printf("over data max size!\n");
            break;
        } else if(p != buffp){
            data[counter++]=value;
            if(*p == '\0' || *p == '\r'|| *p == '\n')
                continue;
            buffp = p;
            goto next;
        } else {
            if(*p == '$')
                break;
            printf("format error\n");
            break;
        }
    }
    //check code 
    for(i=0;i<counter;++i){
        printf("data[%d]=%d\n",i, data[i]);
    }
    return 0;
}

OUTPUT:

1 2 3
123
456
99 $
data[0]=1
data[1]=2
data[2]=3
data[3]=123
data[4]=456
data[5]=99

12345

4
$
data[0]=12345
data[1]=4

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.