help with code..

C, C++, Visual C++, C++.Net Topics
ghostrider_gr
Sergeant
Sergeant
Posts: 17
Joined: Mon Apr 19, 2010 1:01 am

help with code..

Post by ghostrider_gr » Thu Jan 13, 2011 8:19 pm

well i have some questions.. its given to me a routine so as to read large inputs faster than using scanf.. the problem is that i do not quite understand what this rutine does?

the code is:

Code: Select all

#include <stdio.h>
#define BSIZE 1<<16

char buffer[BSIZE];
int bpos = 0, bsize = 0;

int readInt() 
{
	int d = 0, x = 0;
	char c;

	while(1) 
    {
		if (bpos >= bsize) 
        {
			bpos = 0;
			if (feof(stdin)) return x;
			bsize = fread(buffer, 1, BSIZE, stdin);
		}

		c = buffer[bpos++];
		if (c >= '0' && c <= '9') { x = x*10 + (c-'0'); d = 1; }
		else if (d == 1) return x;
	}
	return -1;
}
and my questions are:

why

Code: Select all

c = buffer[bpos++];
what's the purpose of it? and why c=buffer[bpos++] and not [bsize++] so as to take the end of the array.. what's the value of bpos in that assignment?

and secondly, i dont get at all the last if, else-if clause...

i would appreciate any help..
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: help with code..

Post by Neo » Thu Jan 13, 2011 11:51 pm

Okay.. First of all, you must understand the purpose of each and every variable in the code.

Lets take the most important two variables.

bpos - This is the byte position within the buffer. Whenever we read a byte we advance the position by 1.
bsize - This is the buffer size. Whenever we use fread, it returns the number of bytes it actually read from file. Since we read BSIZE blocks, bsize will be always equals to BSIZE except the last read that reach end of file.

Now we can try understanding the code from there.

Code: Select all

c = buffer[bpos++];
Here, we read the byte on current position (initially bpos is 0) and advance the byte position.

Say the byte array in array buffer is {'1', '2', '3', '4', '5' ......... }.
When it runs the above code, c will become '1' and bpos will set to 1 (from 0).
On the next run, c will become '2' and bpos will set to 2 and so on.

When one block of BSIZE is completely processed, bpos will equals to bsize where the code will read another block on the next call.

The last part that you are not clear is,

Code: Select all

	if (c >= '0' && c <= '9'){
		x = x*10 + (c-'0'); d = 1;
	}
	else if (d == 1){
		return x;
	}
The file you read is a TEXT file (not a BINARY file) so you have readable data on this file when you open this on Notepad.
It will contain numbers like, 1234567.... and so on. When you read this to a char array, it will become {'1', '2', '3', '4', '5' ......... }.

What we do here is, if the character we just read is a number (between char '0' and char '9'), then we multiply the previous value of x by 10 (initially this is 0) and add the integer value of char stored in c. According to the example array I have provided above, x will become 1 after the first iteration on the loop.

On the second iteration on the loop, x will become (1 x 10) + 2 = 12.
On the third iteration on the loop, x will become (12 x 10) + 3 = 123.

This process goes until you find EOF (end of file) or you found a non-number character. In both cases, it returns the value of x.

d is used to stop existing from the function if the first number you read is not a number char. Say our array is {'a', '1', '2' ...... }. Then our first char is 'a' which is not a number and it goes to else if (d == 1){ part which fails since d = 0 initially.

I explain a bit on the following code.

Code: Select all

c-'0'
Say you have just read '1' to c. The ACSII value for char '1' is 49. The ASCII value of char '0' is 48. So when you do c - '0', it is 49 - 48 = 1. See ASCII table here.
ghostrider_gr
Sergeant
Sergeant
Posts: 17
Joined: Mon Apr 19, 2010 1:01 am

Re: help with code..

Post by ghostrider_gr » Fri Jan 14, 2011 12:46 am

thanks a lot! i got many of them on my own..

anyway my attempt is this:
i want to read first 2 numbers, N,M,B and for the next M lines i will read 3 numbers per line, and store them in an array..
for example, if the input is:
2 3 50
1 2 3
4 5 6
7 8 9
i must have N=2, M=3,B=50
and an array A ={1,2,3
4,5,6
7,8,9}

my code is:

Code: Select all

#include<stdio.h>
#include<stdlib.h>
#define BSIZE 1<<16


int N,M,B;
int A[10000][3];

int main() {
    char buffer[BSIZE];
    int bpos = 0, bsize = 0,x,element=0,rows=0,column=0;
    int i,c,d;
    
    scanf("%d %d %d",&N,&M,&B);  
    while(1) 
    {
		if (bpos >= bsize) 
        {
			bpos = 0;
			if (feof(stdin)) break;
			bsize = fread(buffer, 1, BSIZE, stdin);
		}

		c = buffer[bpos++];
		if (c >= '0' && c <= '9') { x = x*10 + (c-'0'); d = 1; }
		else if (d == 1) {
             element=element+1;
             rows=(element/3)+1;
             column=(element%3)+1;
             A[rows][column]=x;
             }
        if ((element==M)&&(column==3)) break;
	}
	for (i=1;i<M;i++) {
        printf("%d   %d   %d\n",A[i,1],A[i,2],A[i,3]);
    }
    system("pause\n");
    return 0;
     
}
but after i give the first 3 numbers, no matter what i type i see nothing on screen.. any sollutions..?

note that the input may be large and the programme must run in under 1 sec, so with scanf i will waste all my time in reading..
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: help with code..

Post by Neo » Fri Jan 14, 2011 1:45 am

Your requirement is not clear and your code is very badly organised. No indents maintained.
Can you reorganize it and explain your problem by naming what is N, M and B.

I don't see that you open a file for reading with fopen.

The other point is, we can't write codes for you. We just can try to give you tips by looking at your codes. I guess this is homework?
ghostrider_gr
Sergeant
Sergeant
Posts: 17
Joined: Mon Apr 19, 2010 1:01 am

Re: help with code..

Post by ghostrider_gr » Fri Jan 14, 2011 1:57 am

Neo wrote:Your requirement is not clear and your code is very badly organised. No indents maintained.
Can you reorganize it and explain your problem by naming what is N, M and B.

I don't see that you open a file for reading with fopen.

The other point is, we can't write codes for you. We just can try to give you tips by looking at your codes. I guess this is homework?
not its not homework.. i mean my exercise works perfectly but for large inputs runs for more than 1 sec.. and it must run in less than 1 sec.. and its not the problem of the algorithm, but i am wasting too much time if i read using scanf(it was what i did before)..

thats why i didn't mentioned what is N,M,B because i only want help in reading my input...

so i will make myself clear:

the input will be for example:
6 5 50
1 2 10
1 3 20
2 4 10
2 5 40
3 5 10

and i expect to have read something like this:
N=6, M=5, B=50
and for the next M=5 lines i want to read through the fread and i expect this to happen:
A[1,1]=1 A[1,2]=2 A[1,3]=10
A[2,1]=1 and so on...

i am not asking on an algorithm..so i dont think there is a problem.. and i have given you my code... but i dont know what is wrong..
when you say, i dont read from a file what do you mean.. i have set the stdin, so as to type the input ? is it wrong?
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: help with code..

Post by Neo » Fri Jan 14, 2011 2:24 am

This is a very simple requirement and getting it sorted with your code is not easy.
Can you write a pseudo code first so you will understand what is required here rather than changing a code which is written for something else.

Something like,

Code: Select all

Read N, M, B

Read from stdin to buffer

for i = 1 to M

     // Read each line of code separated by space char from buffer and store to array (ex: Arr[i][0] = x)
     // You can use strtok in C++ to get this done easily.

next i

// You have input on array now

// Write the processing part
ghostrider_gr
Sergeant
Sergeant
Posts: 17
Joined: Mon Apr 19, 2010 1:01 am

Re: help with code..

Post by ghostrider_gr » Fri Jan 14, 2011 6:56 am

Neo wrote:This is a very simple requirement and getting it sorted with your code is not easy.
Can you write a pseudo code first so you will understand what is required here rather than changing a code which is written for something else.

Something like,

Code: Select all

Read N, M, B

Read from stdin to buffer

for i = 1 to M

     // Read each line of code separated by space char from buffer and store to array (ex: Arr[i][0] = x)
     // You can use strtok in C++ to get this done easily.

next i

// You have input on array now

// Write the processing part
yes this is what i have in mind, but i still have a question...

if the buffer size is smaller than the data, then the process must be done more than times.. am i right?
when you say "read each line of code" you mean search in the buffer, right?
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: help with code..

Post by Neo » Fri Jan 14, 2011 10:55 am

Yes. That's right....
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: help with code..

Post by Neo » Wed Jan 19, 2011 2:18 am

Ghost, How it is going?
User avatar
SemiconductorCat
Major
Major
Posts: 455
Joined: Mon Aug 22, 2011 8:42 pm
Location: currently in hyperspace

Re: help with code..

Post by SemiconductorCat » Tue Aug 23, 2011 4:04 am

so you don't need to use scanf right?

what you need is to write your own lexer to parse it.

There is something called Finite State Machines for that.
Google for finite state machines. It's easy to code a finite state machine for this.
That's the formal method that I'm doing if this kind of thing I had met in the industry.
Post Reply

Return to “C/C++ Programming”