Read one char at a time from text file?

  • (2 Pages)
  • +
  • 1
  • 2

18 Replies - 10786 Views - Last Post: 23 January 2010 - 03:15 PM Rate Topic: -----

#1 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Read one char at a time from text file?

Posted 22 January 2010 - 03:13 PM

My assignment in C++ class for this week is to write 2 programs. One to encrypt a four-digit integer and one to decrypt that same integer. The first program gets the ints from the user and writes them to a text file after encrypting each number. I finished that part, and it works like I want it to.

Now I need to write the decryption part, and read each line of the file that is written by the first program. I want the program to decrypt each integer and then print them to another file.

How do I read just one character on a line so that I can put it into an array? Also, how do you make sure you get all the characters for each line, but only one line at a time? I know there are other (probably better?) ways of doing this, such as read the whole line and then break up the integer into parts in order to work with each part. But I prefer using an array.

This is the function that I think needs changing.

//read nums from file into array
void read(int nums[], int SIZE, ifstream& inData) {
	 int nextNum;
	 //read first line from the file //how do I read one char at a time from file?
	inData >> nextNum;
	//show error if file not found
	if(!inData)
	{
		  cout<< "Can't open input file.\n";
		  getchar();
	}
	
	//while there are more lines to read from file
	int i = 0; //counter
	while(inData){	 
		  nums[i] = nextNum;		
		  //read another line...this will put each line into an element in the array
		  //so the whole file is read into one array instead of each line in one array
		  //with each char in the line put into one element of the array
		  inData >> nextNum;
		  i++;   
	}   
}


This program does work in that it will read the file and swap the values that I told it to swap. They're just not the right values.

Here is the entire 2nd program (unfinished, of course)

#include<iostream>
#include<fstream> //for file reading & writing

using namespace std;

//read nums from file into array
void read(int nums[], int SIZE, ifstream& inData) {
	 int nextNum;
	 //read first line from the file //how do I read one char at a time from file?
	inData >> nextNum;
	//show error if file not found
	if(!inData)
	{
		  cout<< "Can't open input file.\n";
		  getchar();
	}
	
	//while there are more lines to read from file
	int i = 0; //counter
	while(inData){	 
		  nums[i] = nextNum;		
		  //read another line...this will put each line into an element in the array
		  //so the whole file is read into one array instead of each line in one array
		  //with each char in the line put into one element of the array
		  inData >> nextNum;
		  i++;   
	}   
}

//swap the first digit with the second, swap the thrid digit with 
//the fourth 
void swap(int nums[]){
	 int temp = nums[0];
	 //swap first two numbers
	 nums[0] = nums[1];
	 nums[1] = temp;
	 //swap second two numbers
	 temp = nums[2];
	 nums[2] = nums[3];
	 nums[3] = temp;
}

//print the decrypted integer to the screen and to a file 
void print(int nums[], int SIZE, ofstream& outData){   
	//print to screen and write to file. 
	for(int i = 0; i<SIZE; i++){
		cout<<nums[i];
		outData << nums[i];
   
	//start next number on a new line
	cout << endl;
	outData << endl; 
	}
}

int main() {
	const int SIZE = 7;
	int nums[SIZE];
	
	//open file to read
	ifstream inData;
	inData.open("EncFile.txt"); 
	
	//open file to write
	ofstream outData;
	outData.open("DecFile.txt");  
	
	
	read(nums, SIZE, inData);
	//replace(nums, SIZE);
	swap(nums);
	print(nums, SIZE, outData); 
	
	inData.close();
	outData.close();   
	
}
//Write a separate program(a second program, gosh) that inputs an encrypted 
//four-digit integer and decrypts it to form the original number.



Is This A Good Question/Topic? 0
  • +

Replies To: Read one char at a time from text file?

#2 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Read one char at a time from text file?

Posted 22 January 2010 - 03:21 PM

You could read one character at a time. See istream::read

Or you could read in the entire line and treat the string as an array. See string::operator[]

See getline in the Strings library

This post has been edited by n8wxs: 22 January 2010 - 03:23 PM

Was This Post Helpful? 1
  • +
  • -

#3 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 862
  • View blog
  • Posts: 3,982
  • Joined: 09-June 09

Re: Read one char at a time from text file?

Posted 22 January 2010 - 03:35 PM

you can just use istream::get() to read a file char by char

http://www.cplusplus...am/istream/get/
example
vector<char> readbyChar(ifstream &file)
{
	vector<char>data(0);
	char c;
	while(file.get(c))
	{
		data.push_back(c);
	}
	return data;
}


This post has been edited by ImaSexy: 22 January 2010 - 03:35 PM

Was This Post Helpful? 1
  • +
  • -

#4 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2209
  • View blog
  • Posts: 9,183
  • Joined: 18-February 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 03:37 PM

well you can read a char at a time by just opening the file... but there is a problem here:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main() {
	ofstream outfile ("numbers.txt");
	//write out some random numbers...
	srand(time(0));
	for(int i = 0; i < 10; i++) {
		int number = 1000 + (rand() % 1000);
		outfile << number << endl;
	}
	outfile.close();
	
	//now to read some:
	ifstream infile("numbers.txt");
	char ch;
	int count = 0;
	while(infile >> ch) {
		cout << ch;
		if (count % 4 == 3) { cout << endl; }
		count++;		
	}
	infile.close();
	return 0;
}



The problem here is that there is not real way of telling when we reach the end of a line. I used count % 4 == 3 since I knew the numbers would all be 4 chars...

If you don't know that the file has a specific format then you have a couple of options. You can use getLine() with a string and then grab the chars from the string, or you can open the file in binary mode when you will see the whitespace chars.
Was This Post Helpful? 1
  • +
  • -

#5 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 04:16 PM

Thank you guys. :) I will try these suggestions after I get back to the desktop computer. This laptop has no compilers on it. :(

One more thing, when you are reading one char at a time, will it read 0's? If one of four-digit ints is 0000, will it read them all? The way my program is right now, it only reads prints one zero, or if there's a number like 0987 it will only read print 987. I'm not sure what it's reading, I only know for sure what it's printing.
Was This Post Helpful? 0
  • +
  • -

#6 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 862
  • View blog
  • Posts: 3,982
  • Joined: 09-June 09

Re: Read one char at a time from text file?

Posted 22 January 2010 - 04:57 PM

I would create a structure array and store a new line in every index of that structure.

example (compiled but not tested)

enum
{
	FILE_BAD,
	SUCCESS
};

struct line_info
{
	char line[250];

	line_info(void)
	{
		memset(line,'\0',sizeof(line));
	}
};

int filesize(ifstream &file)
{
	int count = 0;
	string temp = "";
	while(getline(file,temp))
		count++;
	file.clear();
	file.seekg(ios::beg); //reset file point back to the beginning
	
	return count;
}

int read( ifstream& inData, line_info*lines, int &SIZE) 
{
	if(!inData.is_open())
		return FILE_BAD; //return if bad file

	SIZE = filesize(inData);
	//allocate some space for all of the lines 
	lines = new line_info[SIZE];


	char c;

	int s_index = 0; //index for struct
	int l_index = 0; //index for array in struct
	

	while(inData.get(c)&&s_index<SIZE)
	{
	
		if(c == '\n') //if a new line appears in file
		{
			s_index++; //incriment to an empty struct
			l_index = 0; //clear line buffer back to zero
			continue;
		}

		lines[s_index].line[l_index] = c;
		
	}
	return SUCCESS;
}

This post has been edited by ImaSexy: 22 January 2010 - 04:59 PM

Was This Post Helpful? 0
  • +
  • -

#7 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 05:47 PM

What I need to do besides just reading a char at a time is to read or save it as an int.

This works if I was going to save it as a char, but I need to perform arithmetic operations on each number after it's in the array. It doesn't put the correct numbers into the array. See?

 ifstream is;
 char c;
 int i =0;
	is.open("EncFile.txt");
  while (is.good())	 // loop while extraction from file is possible
  {
	c = is.get();	   // get character from file
	if (is.good())
	  cout <<"c"<< c<<endl;
	  nums[i]=is.get();
	  cout<<endl<<nums[i]<<" is nums i"<<endl;
	  i++;
  }
}


If there's a way to change c's value from char to int and then place it in the array I guess that would work. Though it seems like a roundabout way of doing things.
Was This Post Helpful? 0
  • +
  • -

#8 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Read one char at a time from text file?

Posted 22 January 2010 - 06:03 PM

Have a look at
// matrices.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"

#include <iostream>
#include <fstream>

using namespace std;

void read (int [], int, ifstream&);
void swap (int []);
void print(int [], int, ofstream&);

int _tmain(int argc, _TCHAR* argv[]) {
	const int SIZE = 7;
	int nums[SIZE];

	//open file to write
	ofstream outData;
	outData.open("oliveoyl.txt", ios::out | ios::trunc);  

	for (int i = 0; i < SIZE; i++) {
		outData.write((char *) &i, 1);
	}

	outData.close();  

	//open file to read
	ifstream inData;
	inData.open("oliveoyl.txt");

	//open file to write
	//	ofstream outData;
	outData.open("DecFile.txt");  


	read(nums, SIZE, inData);
	//replace(nums, SIZE);
	swap(nums);
	print(nums, SIZE, outData);

	inData.close();
	outData.close();  

	system("pause");
	return 0;
}
void read(int nums[], int SIZE, ifstream& inData) {
	char c;

	for (int i = 0; i < SIZE; i++) {
		inData.read(&c, 1);

		if (inData.good())
			nums[i] = c;

		else {
			cout << "Couldn't read byte #" << i << endl;
			inData.clear();
		}
	}
	// int nextNum;
	// //read first line from the file //how do I read one char at a time from file?
	//inData >> nextNum;
	////show error if file not found
	//if(!inData)
	//{
	//	  cout<< "Can't open input file.\n";
	//	  getchar();
	//}

	////while there are more lines to read from file
	//int i = 0; //counter
	//while(inData){	
	//	  nums[i] = nextNum;		
	//	  //read another line...this will put each line into an element in the array
	//	  //so the whole file is read into one array instead of each line in one array
	//	  //with each char in the line put into one element of the array
	//	  inData >> nextNum;
	//	  i++;  
	//}  
}

//swap the first digit with the second, swap the thrid digit with
//the fourth
void swap(int nums[]){
	int temp = nums[0];
	//swap first two numbers
	nums[0] = nums[1];
	nums[1] = temp;
	//swap second two numbers
	temp = nums[2];
	nums[2] = nums[3];
	nums[3] = temp;
}

//print the decrypted integer to the screen and to a file
void print(int nums[], int SIZE, ofstream& outData){  
	//print to screen and write to file.
	for(int i = 0; i<SIZE; i++){
		cout<<nums[i];
		outData << nums[i];

		//start next number on a new line
		cout << endl;
		outData << endl;
	}
}



Here's the output:

Quote

1
0
3
2
4
5
6
Press any key to continue . . .

Was This Post Helpful? 1
  • +
  • -

#9 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 862
  • View blog
  • Posts: 3,982
  • Joined: 09-June 09

Re: Read one char at a time from text file?

Posted 22 January 2010 - 06:47 PM

Cant u just use atoi to covert each char to an int
Was This Post Helpful? 0
  • +
  • -

#10 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2209
  • View blog
  • Posts: 9,183
  • Joined: 18-February 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 07:18 PM

Why use atoi for 1 char...

digit = ch - '0';

remember that chars ARE numbers.
Was This Post Helpful? 1
  • +
  • -

#11 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 862
  • View blog
  • Posts: 3,982
  • Joined: 09-June 09

Re: Read one char at a time from text file?

Posted 22 January 2010 - 08:26 PM

oh your completly correct Nick, i seem to always forget your can still perform aritmetic operation on chars.
Was This Post Helpful? 0
  • +
  • -

#12 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 09:40 PM

Well I finally got it working. Thank you all for your kind help and nudges in the right direction. :)

This is actually a little different than what I had originally intended, but hey...as long as it works, eh?

Thanks to baavgai, too. You're the coolest! B)

#include<iostream>
#include<fstream> //for file reading & writing
#include<conio.h> //for getch()

using namespace std;

//print the decrypted integer to the screen and to a file 
void print(string nums[], ofstream& outData){   
	//print to screen and write to file. 
	for(int i = 0; i<4; i++){
		cout<<nums[i];
		outData << nums[i];
	} 
}

//swap the first digit with the second, swap the third digit with 
//the fourth 
void swap(string nums[], ofstream& outData){
	 string temp = nums[0];
	 //swap first two numbers
	 nums[0] = nums[1];
	 nums[1] = temp;

	 //swap second two numbers
	 temp = nums[2];
	 nums[2] = nums[3];
	 nums[3] = temp;
	 print(nums, outData);
}

//replace numbers 
void replace(ifstream& inData, ofstream& outData){ 
	char ch;
	//open file to read 
   inData.open("EncFile.txt");
   string nums[4]; //array to hold each character
   while (inData.good()){ // loop while extraction from file is possible
		 for(int i =0; i< 5; i++){  //5 because 4 integers plus new line character will be read
			
			 ch = inData.get();   // get character from file
			 if (inData.good()){
			 //for each char in string, change it back to original (before swapping)
				  switch(ch){
					   case '0': ch = '5';
					   break;
					   case '1': ch = '6';
					   break;		  
					   case '2': ch = '7';
					   break;		  
					   case '3': ch = '8';
					   break;		  
					   case '4': ch = '9';
					   break;		  
					   case '5': ch = '0';
					   break;		  
					   case '6': ch = '1';
					   break;		  
					   case '7': ch = '2';
					   break;		  
					   case '8': ch = '3';
					   break;		  
					   case '9': ch = '4';
					   break; 
					   case '\n': ch = '\n';					  
				  }//end switch
				  if(ch == '\n'){ //don't add new line character to array			 
				  }//end if
				  else{
					  nums[i] = ch;//only if ch is not new line
					  
				  }//end else
			 }//end if
		 }//end for
		 swap(nums, outData); 
			   outData<<endl;
			   cout<<endl;	 

   }//end while
}//end replace()

int main() {

	ifstream inData;
	ofstream outData;
	//open file to write
	outData.open("DecFile.txt");  
	
	replace(inData, outData);

	inData.close();
	outData.close();   
	getch(); 
}
//Write a separate program(a second program, gosh) that inputs an encrypted 
//four-digit integer and decrypts it to form the original number.

Was This Post Helpful? 0
  • +
  • -

#13 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 10:47 PM

Now I see why programmers cuss so much! :blink:

Is there a way to fix this so that it will still be able to read one char at a time, and also do a priming read (or whatever it takes to make it work properly) so it won't go past the end of the file and input one extra line into my text file?

   while (inData.good()){ // loop while extraction from file is possible
		 for(int i =0; i< 5; i++){ //5 because 4 integers plus new line character will be read   
			 ch = inData.get(); // get character from file



I tried
inData>>ch;
while(inData>>ch)



But it messed up the whole thing. :(
Was This Post Helpful? 0
  • +
  • -

#14 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2209
  • View blog
  • Posts: 9,183
  • Joined: 18-February 07

Re: Read one char at a time from text file?

Posted 22 January 2010 - 10:57 PM

you know... rather than that long switch you could use a little math formula:
#include<iostream>

using namespace std;

char encode(char ch) {
	if (ch >= '0' && ch <= '9') {
		ch = (ch - '0' + 5 ) % 10 + '0';
	}
	return ch;
}

int main() {
	for (char ch = '0'; ch <= '9'; ch++) {
		cout << ch << " --> " << encode(ch) << endl;
	}   
	return 0;
}

Was This Post Helpful? 0
  • +
  • -

#15 OliveOyl3471  Icon User is offline

  • Everybody's crazy but me!
  • member icon

Reputation: 134
  • View blog
  • Posts: 6,581
  • Joined: 11-July 07

Re: Read one char at a time from text file?

Posted 23 January 2010 - 09:05 AM

View PostNickDMax, on 22 Jan, 2010 - 11:57 PM, said:

you know... rather than that long switch you could use a little math formula


That's pretty cool how you can do math on a character like that. And it shortens the code. :)

I did get mine working, finally. Maybe, now that it works, I'll try making it work better. Of course I'm going to hand the thing in, as is, because I'm kind of sick of it at the moment and I really want to make sure I get credit for it...in case the computer messes up or something. But doing math on chars is pretty neat. B)

Here's how I changed it to make it work like I want:

//replace numbers 
void replace(ifstream& inData, ofstream& outData){ 
   //open file to read 
   inData.open("EncFile.txt");
   char ch;
   string nums[4]; //array to hold each character
   if(!inData){ //make sure file opens
		 cout<< "Can't open input file.\n";
		 getchar();
   }
   ch = inData.get(); // get character from file, priming read
   while (inData.good()){ // loop while extraction from file is possible
		 for(int i =0; i< 5; i++){ //5 because 4 integers plus new line character will be read   
			 if (inData.good()){ 
				  //for each char in string, change it back to original (before swapping)
				  switch(ch){
					   //long old switch here
				   
				  }//end switch
				  if(ch == '\n'){ //don't add new line character to array			 
				  }//end if
				  else{
					  nums[i] = ch;//only if ch is not new line
					  
				  }//end else
			 }//end if
			 ch = inData.get(); // get another character from file
		 }//end for
		 swap(nums, outData);
		 outData<<endl;
		 cout<<endl;	 
   }//end while
}//end replace()


Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2