Showing posts with label output. Show all posts
Showing posts with label output. Show all posts

Saturday, August 7, 2010

Tricks for c++ IO

#include<iostream>
Include this file whenever using C++ I/O
#include<iomanip>
This file must be included for most C++ manipulators. 
If you don't know what a manipulator is, don't worry. 
Just include this file along with iostream and you can't go wrong
#include<fstream>
Include this file whenever working with files.


By default, leading whitespace (carriage returns, tabs, spaces) is ignored by cin.
Given:

int i;
float fl;
std::cin >> fl;
std::cin >> i;

1. And you type: 3.1442 3.14 is read into fl . The carriage return (newline) following the 3.14 is still sitting on the input buffer.
2. Since std::cin ignores whitespace, the first return is "eaten" by std::cin >> i . Then the integer 42 is read into i and the second return is left on the input buffer.

std::cin.getline() can run into problems when used with std::cin >> var.

* getline can be provided a third argument--a "stop" character. This character ends getline's input. The character is eaten and the string is terminated. Example:
std::cin.getline(str, 100, '|')
* If std::cin.getline() is not provided a "stop" character as a third argument, it will stop when it reaches a newline.

Given:

float fl;
std::cin >> fl;
char str[101]
std::cin.getline(str, 101);

1. And you type: 3.14
2. 3.14 is read into fl . The newline following the 3.14 is still sitting on the input buffer.
3. std::cin.getline(str, 101) immediately processes the newline that is still on the input buffer. str becomes an empty string.
4. The illusion is that the application "skipped" the std::cin.getline() statement.

The solution is to add std::cin.ignore(); immediately after the first std::cin statement. This will grab a character off of the input buffer (in this case, newline) and discard it.

std::cin.ignore() can be called three different ways:

1. No arguments: A single character is taken from the input buffer and discarded:
std::cin.ignore(); //discard 1 character
2. One argument: The number of characters specified are taken from the input buffer and discarded:
std::cin.ignore(33); //discard 33 characters
3. Two arguments: discard the number of characters specified, or discard characters up to and including the specified delimiter (whichever comes first):
std::cin.ignore(26, '\n'); //ignore 26 characters or to a newline, whichever comes first

Reading in numbers directly is problematic

* If std::cin is presented with input it cannot process, std::cin goes into a "fail" state
* The input it cannot process is left on the input stream.
* All input will be ignored by std::cin until the "fail" state is cleared: std::cin.clear()
* A routine that reads a number directly should:
1. Read in the number
2. Check to see that the input stream is still valid
3. If the input stream is not good (!std::cin)
1. Call std::cin.clear() to take the stream out of the "fail" state.
2. Remove from the stream the input that caused the problem: std::cin.ignore(...)
3. Get the input again if appropriate or otherwise handle the error

Inputing numbers directly, version 1:

#include //for numeric_limits
float fl;
int bad_input;
do{
bad_input=0;
std::cin >> fl;
if(!std::cin)
{
bad_input=1;
std::cin.clear();
std::cin.ignore(std::numeric_limits::max(),'\n');
}

}while(bad_input);

Inputing numbers directly, version 2:

#include //for numeric_limits
float fl;
while(!(std::cin >> fl))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits::max(),'\n');
}

A note on limits. If your compiler doesn't support std::numeric_limits::max(), an alternative is to use the c-style method for determining the maximum integer allowed:

#include
...
std::cin.ignore(INT_MAX, '\n');

Using getline to input numbers is a more robust alternate to reading numbers directly

#include
...
int i;
float fl;
char temp[100];

std::cin.getline(temp, 100);
fl=strtof(temp,0);
std::cin.getline(temp, 100);
i=strtol(temp,0,10);

* getline will read both strings and numbers without going into a "fail" state.
* Include cstdlib to use the converter functions: string-to-long-integer (strtol), string-to-double (strtod), string-to-float (strtof), and string-to-long-double (strtold). Refer to a reference for more information on the second (and third for strtol) arguments to these converter functions.

Once a file is opened, it may be used exactly as std::cin is used.

std::ifstream someVarName("data.txt");
float fl;
char temp[100];
someVarName.getline(temp, 100);
fl=strtof(temp);
int i;
someVarName >> i;

When reading an entire file, embed the file input inside of the loop condition

std::ifstream inf("data.txt");
char temp[100];
while(!inf.getline(temp, 100).eof())
{
//process the line
}

* the loop will exit once the end of the file is reached

Getline can be told to stop grabbing input at any designated character

char temp[100];
std::cin.getline(temp, 100, '|');

* If only two arguments are supplied to getline, getline will stop at the end of the line (at the newline character).
* If three arguments are supplied to getline, getline will stop at the character designated by the third argument.
* The stop character is not copied to the string.
* The stop character is "eaten" (removed from the input stream).

Delimited files can easily be read using a while loop and getline.
Given data file:

John|83|52.2
swimming|Jefferson
Jane|26|10.09
sprinting|San Marin

Process using:

std::ifstream inf("data.txt");
char name[30];
while(!inf.getline(name, 30, '|').eof())
{
Athlete* ap;
char jersey_number[10];
char best_time[10];
char sport[40];
char high_school[40];
inf.getline(jersey_number, 10, '|'); #read thru pipe
inf.getline(best_time, 10); #read thru newline
inf.getline(sport, 40, '|'); #read thru pipe
inf.getline(high_school, 40); #read thru newline
ap = new Athlete(name, strtod(number), strtof(best_time), sport, high_school);
//do something with ap

}

* In a delimited file, only the first field should be in the while loop
* For each field: If the field is the last field in the line or the only field in the line, be sure that getline stops at a newline and not some other delimiter

Using C++-style strings

All of the previous examples have assumed that C-style strings (null-terminated character arrays) were being used. C++ provides a string class that, when combined with a particular "getline" function, can dynamically resize to accommodate user input. In general, C++ strings are preferred over C strings.

Here is the same code shown above, this time using C++ strings:

#include
std::ifstream inf("data.txt");
string name;
while(!std::getline(inf, name, '|').eof())
{
Athlete* ap;
std::string jersey_number;
std::string best_time;
std::string sport;
string high_school;
std::getline(inf, jersey_number, '|'); #read thru pipe
std::getline(inf, best_time); #read thru newline
std::getline(inf, sport, '|'); #read thru pipe
std::getline(inf, high_school); #read thru newline
ap = new Athlete(name, strtod(number.c_str()),
strtof(best_time.c_str()), sport, high_school);
//do something with ap

}

How to prepare the output stream to print fixed precision numbers (3.40 instead of 3.4)

std::cout.setf(ios::fixed, ios::floatfield);
std::cout.setf(ios::showpoint);
std::cout.precision(2);

How to set the width of a printing field
Given: int one=4, two=44;

std::cout << one << std::endl.;
//output: "4"

std::cout << setw(2) << one << std::endl.;
//output: " 4"

std::cout.fill('X');
std::cout << setw(2) << one << std::endl.;
//output: "X4"

std::cout.fill('X');
std::cout << setw(2) << two << std::endl.;
//output: "44"

* The default fill character is a space.
* A common fill character when printing numbers is zero "0".

Thursday, December 3, 2009

Some questions on pointers and arrays

1)
main( )
{
static int a[ ] = {0,1,2,3,4};
int *p[ ] = {a,a+1,a+2,a+3,a+4};
int **ptr = p;
ptr++;
printf(“\n %d %d %d”, ptr-p, *ptr-a, **ptr);
*ptr++;
printf(“\n %d %d %d”, ptr-p, *ptr-a, **ptr);
*++ptr;
printf(“\n %d %d %d”, ptr-p, *ptr-a, **ptr);
++*ptr;
printf(“\n %d %d %d”, ptr-p, *ptr-a, **ptr);
}
Answer:
111
222
333
344
Explanation:
Let us consider the array and the two pointers with some address and also sizeof(int) = 2 bytes.
a
elements : 0       1    2     3    4
address  :100 102 104 106 108
p
elements : 100   102  104    106   108
address  :1000 1002 1004 1006 1008
ptr
elements : 1000
address  :2000

After execution of the instruction ptr++ value in ptr becomes 1002, if scaling factor for integer is 2 bytes. Now ptr – p is value in ptr – starting location of array p, (1002 – 1000) / (scaling factor) = 1.
*ptr – a = value at address pointed by ptr – starting value of array a, a+1 - a = 1;
**ptr is the value stored in the location pointed by the pointer of ptr = value pointed by value pointed by 1002 = value pointed by 102 = 1.ie **ptr = *(a+1) = 1
Hence the output of the firs printf is 1, 1, 1.

After execution of *ptr++ increments value of the value in ptr by scaling factor, so it becomes1004.
Hence, the outputs for the second printf are ptr – p = 2, *ptr – a = 2, **ptr = 2.

After execution of *++ptr increments value of the value in ptr by scaling factor, so it becomes1004. Hence, the outputs for the third printf are ptr – p = 3, *ptr – a = 3, **ptr = 3.

After execution of ++*ptr value in ptr remains the same, the value pointed by the value is incremented by the scaling factor. So the value in array p at location 1006 changes from 106 to 108,. Hence, the outputs for the fourth printf are ptr – p = 1006 – 1000 = 3, *ptr – a = 108 – 100 = 4, **ptr = 4.

2)
main ( )
{
static char *s[ ] = {“black”, “white”, “yellow”, “violet”};
char **ptr[ ] = {s+3, s+2, s+1, s}, **p;
p = ptr;
**++p;
printf(“%s”,*--*++p + 3);
}

Answer:
ck
Explanation:
In this problem we have an array of char pointers pointing to start of 4 strings. Then we have ptr which is a pointer to a pointer of type char and a variable p which is a pointer to a pointer to a pointer of type char. p hold the initial value of ptr, i.e. p = s+3.
The next statement increment value in p by 1 , thus now value of p = s+2.
In the printf statement the expression is evaluated *++p causes gets value s+1 then the pre decrement is
executed and we get s+1 – 1 = s . the indirection operator now gets the value from the array of s and adds 3 to the starting address. The string is printed starting from this position. Thus, the output is ‘ck’.

3)

main()
{
int i, n;
char *x = “girl”;
n = strlen(x);
*x = x[n];   //is same as x[0]=x[n];
for(i=0; i
{
printf(“%s\n”,x);
x++;
}
}


Answer:
(blank space)
irl
rl
l
Explanation:
Here a string (a pointer to char) is initialized with a value “girl”. The
strlen function returns the length of the string, thus n has a value 4. The
next statement assigns value at the nth location (‘\0’) to the first location.
Now the string becomes “\0irl” . Now the printf statement prints the string
after each iteration it increments it starting position. Loop starts from 0 to
4. The first time x[0] = ‘\0’ hence it prints nothing and pointer value is
incremented. The second time it prints from x[1] i.e “irl” and the third
time it prints “rl” and the last time it prints “l” and the loop terminates.




#define DIM( array, type) sizeof(array)/sizeof(type)
main()
{
int arr[10];
printf(“The dimension of the array is %d”, DIM(arr, int));
}
Answer:
10
Explanation:
The size of integer array of 10 elements is 10 * sizeof(int). The macro
expands to sizeof(arr)/sizeof(int) => 10 * sizeof(int) / sizeof(int) => 10.
145) int DIM(int array[])
{
return sizeof(array)/sizeof(int );
}
main()
{
int arr[10];
printf(“The dimension of the array is %d”, DIM(arr));
}
Answer:
1
Explanation:
Arrays cannot be passed to functions as arguments and only the pointers
can be passed. So the argument is equivalent to int * array (this is one of
the very few places where [] and * usage are equivalent). The return
statement becomes, sizeof(int *)/ sizeof(int) that happens to be equal in
this case.
146) main()
{
static int a[3][3]={1,2,3,4,5,6,7,8,9};
int i,j;
static *p[]={a,a+1,a+2};
62
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
printf("%d\t%d\t%d\t%d\n",*(*(p+i)+j),
*(*(j+p)+i),*(*(i+p)+j),*(*(p+j)+i));
}
}
Answer:
1 1 1 1
2 4 2 4
3 7 3 7
4 2 4 2
5 5 5 5
6 8 6 8
7 3 7 3
8 6 8 6
9 9 9 9
Explanation:
*(*(p+i)+j) is equivalent to p[i][j].