Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

dvince2

macrumors 6502
Original poster
Mar 6, 2007
283
1
Canada
Hey everyone
I'm in a beginners C class, and have been asked to return the number of each integer inputted from a file
ie. 2 2 4 7 4 2 2 10 9 9 would return
4 2
2 4
1 7
1 10
2 9

I figured this would be easy... but we're not allowed to use arrays of any kind, and only can use printf and scanf from stdio.h

Any help (even just a concept) of how to do this would be great. I don't want the program in C... just an idea how to start this :)
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
Hi

I guess you could use 2 for loops, one inside the other. The outer loop looks for the start of each number in the input string, and the inner loop counts the number of times that number occurs in the remainder of the string.

b e n
 

garethlewis2

macrumors 6502
Dec 6, 2006
277
1
Why oh why don't you students think for yourselves?

This is what you need to do.

In a loop of some type you need to read the first integer as a fixed size. This is your first number you look for. Then increase the file pointer by an integer size and read another number. If this matches the number you are looking for, increase that variable by one, until you reach the end of the file. Then reset the file pointer to the start + 1 where one is the size of an integer. Read the next number. Remember this could cause you a problem with a number you have already read, e.g. 2 in your example. So you need to use a case statement. Since you can't use an array you will have to limit the range of values in the file to something feasible, e.g. 20.

This isn't a difficult problem, you just need to think before posting your homework assignment.
 

John Jacob

macrumors 6502a
Feb 11, 2003
548
9
Columbia, MD
Remember this could cause you a problem with a number you have already read, e.g. 2 in your example. So you need to use a case statement.

I don't see how a case statement would help there.

Here's how I would do it.

First use a while loop to read all the integers from the file. In this loop, use a counter so that we know the number of integers in the file, and use a variable that starts at zero, and which increases if the current integer exceeds that variable's value. This variable will hold the largest integer in the file.

Now, use two for loops. The outer for loop starts at zero and goes upto the largest integer in the file. The inner for loop starts at zero and goes upto the number of integers in the file. In the inner loop, count the number of integers that are of the same value as the outer loop variable.

In pseudocode:

Code:
int func(void)
{
  int current, i, j, largest, total, count;

  largest = 0; total = 0;
  while (1)
  {
    current = getNextIntegerFromFile();
    if (current == -1)
      break;
    if (current > largest)
      largest = current;
    total++;
  }

  for (i = 0; i <= largest; i++)
  {
    count = 0;
    resetToStartOfFile();

    for (j = 0; j < total; j++)
    {
      current = getNextIntegerFromFile();
      if (current == i)
        count++;
    }
    if (count > 0)
      printf("Number of %d is %d\n", i, count);
  }
  return 0;
}

I have assumed that getNextIntegerFromFile reads the next integer from the file, and returns -1 if we have reached EOF. resetToStartOfFile resets the file read pointer to the beginning of the file.

Of course, the problem with this algorithm is that we have to read through the file twice.
 

toddburch

macrumors 6502a
Dec 4, 2006
748
0
Katy, Texas
Of course, the problem with this algorithm is that we have to read through the file twice.

Actually, the resetToStartOfFile is in the wrong place, and you will be reading (you need to read) the file largest + 1 times.

Which, may be perfectly acceptable for this assignment; it's a beginning C class, not a 4th year optimization class.

Todd
 

lazydog

macrumors 6502a
Sep 3, 2005
709
6
Cramlington, UK
First use a while loop to read all the integers from the file. In this loop, use a counter so that we know the number of integers in the file, and use a variable that starts at zero, and which increases if the current integer exceeds that variable's value. This variable will hold the largest integer in the file.

I think you might be able to get rid of this step. All you need to do when reading in the numbers in the inner loop is check if it the number is greater than the index number in the outer loop. If it is you know you need to loop round again. Also if you keep track of the smallest number greater than the current outer loop index, you can 'skip' ahead to that number in the outer loop instead of stepping through the integers by 1 each time.

Probably as clear as mud but I hope it helps.

b e n
 

GeeYouEye

macrumors 68000
Dec 9, 2001
1,669
10
State of Denial
If the maximum number is low, you could just have something like

int ones, twos, threes, fours...;
foreach number in file
{
switch (atoi(number))
{
case 1: ones++;
...
}
}

And then print your output.
 

toddburch

macrumors 6502a
Dec 4, 2006
748
0
Katy, Texas
I wish we got more background info on these questions.

For instance, if this week's topic of interest was BIT FLAGS, then a solution using bit flags would be appropriate. If this week's topic was on searching a string for matching patterns, then those could have been emphasized in yet another solution.

Or, perhaps next week's topic is array's, and this exercise was given to the student so he/she could gain an appreciation for the worth of an array.

Todd
 

ChrisA

macrumors G5
Jan 5, 2006
12,913
2,158
Redondo Beach, California
Here is the solution I think is the "most cool".

1) forget that these are numbers you are reading.
they are simply strings seporated by white space.

Write a function that will given on string, find it inside
a second string and if found remove it from the
second string. The function returns 1 if found else 0
Searching and removing is easy if you use strstr and
strcpy. I think you can do this function in 2 or 3 lines of code
(hint strcpy(foobar[3], foobar[6]) cuts out a segment of
the string foobar. strstr returns a pointer to the thing to
be cut out.)
use srttok to find first integer. Pass this and the whole
string to above. Call self recursively until zero is returned
keeping count of ones

on zero returned print substring and counter

You now have a sting with all occurances of the fist
integer removed.
Repeat until the sting us used up that is while(string[0])

The above would actually count up words in a text book
even if there were 10,000 different words because it uses
the textbook itself as memory.

Details are intensionally left out.

The key here is that you don't need to keep track of what
has been counted. delete it from the string as you count
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.