Simple text editing program in C++ [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I got a little bit of trouble creating a program that edits text in C++. Keep in mind that I'm still at the beginning of programing. Here is what I must do:
Some text is placed in text file F. I must write a program-editor, which based on the file F, commands and data from the keyboard creates the file FF. The program-editor must recognize and process the following commands:
AN - insert text after the n-th row;
IN - insert text before the n-th row;
CM,N - substitution of the rows from m-th to n-th;
DM,N - deleting the rows from m-th to n-th;
E - end of editing;
where m and n are the number of rows in the file F.The commands are recorded one on row and are made as a menu.
This is the program. I researched a lot in the web about text editing and there are some text editing programs' source codes, but I guess I'm still in the beginning of programing and I find those source codes really difficult to understand. I'm concerned about few things:
Must I manually put text in the text file F and must I add another option in the menu about adding text;
The other thing is about the commands - how do I find and use the different rows from the text so I can insert, substitute and delete rows;
Well that is all. If you have the time please help me, because I really need to know how this program must be done in a not so complicated way and I think it got some valuable things that I could learn from it. Thanks in advance !

In pseudo-code, you ll find every real function you ll need in the documpentation.:
You ll need to write parse() yourself, all vec.something and input.something are real vector or string function, under a different name, you ll need to search the documentation.
open, close and writeinfile are io function under different name too (and different parameters), again, see the doc
getuserinput is also a renamed basic io function.
The reason I write this is to give you an idea of how to do this, it is not the solution spoon feeded to you, think of it as the algorithm, if you can do your homework without it, it is far better than using it. Also, learn to search the doc, it is really useful
vector<string> vec
int n, m
string input, output
//Open the file
open(your_file)
//Store every line in a string in the vector
while(input != EOF)
{
input = getalinefrom(file)
vec.add(input)
}
//You don t need the file for now, so close it
close(file)
//Create your 'menu', presuming text based, if graphical, well...
do
{
//Get user choice
input = getuserinput()
//Every command is just a letter, so check it to know what to do
if(input.firstchar == 'A')
{
//Parse the input to get n
n = parse(input)
//Get the line to add
input = getuserinput()
//Add it before n
vec.addafter(n, input)
}
else if (input.firstchar == 'I')
{
//Parse the input to get n
n = parse(input)
//Get the line to add
input = getuserinput()
//Add it before n
vec.addbefore(n, input)
}
else if (input.firstchar == 'C')
{
//Well, I don t see what is substitution so I ll let you try
}
else if (input.firstchar == 'D')
{
//Get n and m
n = parse(input)
m = parse(input)
//Presuming n < m, you ll need to check for error
while(n < m)
{
vec.deleterow(n)
n = n + 1
}
}
//Go out of the loop at E since it s the end of the app
}while(input != "E");
//Concatene every line
n = 0
do
{
output = output + vec.contentofrow(n)
}while(n < vec.length)
//Open the file again, with correct flag it will erase it content
open(file)
//Write your new content
writeinfile(file, output)
//Close the file
close(file)
return 0;

Related

Reading from 3 column txt file to different arrays [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I want to read a three column and N row txt file to three different arrays:
int N=100;
double x[N],
y[N],
z[N];
ifstream reading;
reading.open("reading.txt");
reading.close();
What should I write in the empty region? x[j], y[j], z[j] should be element in j'th row and first, second and third column respectively.
Once you get the input file stream, it will be similar to reading from a standard input.
As a hint I can say, what about reading every integer and then store them appropriately. For example,
1 2 3
4 5 6
7 8 9
Now you read everything like this
while (redaing>> num) {
// here you would know whether you are reading the first number
// or second number or third.
// x[xi] = num or y[yi]=num or z[zi]=num
}
Also you need to do something before you start reading from a file using the input file stream.
Have this check to make the program more safe.
if (!reading) {
cerr << "Unable to open file reading.txt";
exit(1); // call system to stop
}
A solution would be like this:
int xi=0,yi=0,zi=0,iter=0;
while(redaing >>num){
if(iter%3==0)x[xi++]=num;
else if(iter%3 ==1)y[yi++]=num;
else
z[zi++]=num;
iter++;
}
More succintly as pointed by user4581301
while(redaing >>x[xi++]>>y[yi++]>>z[zi++]){
//..do some work if you need to.
}
Also another from comment to limit the 100 line reading is [From comment of user4581301]
int index = 0;
while(index < 100 && redaing >>x[index]>>y[index]>>z[index] ){
index++;
}
A better solution:
vector<int> x,y,z;
int a,b,c;
while(reading>>a>>b>>c){
x.push_back(a);
y.push_back(b);
z.push_back(c);
//..do some work if you need to.
}
I'm kind of confused on the wording of your question could you try and reword It? Also if you want to read to the nth row I would use a while loop with the condition being while not end of file. Also you may consider using a vector since you don't know how large of an array you want to create.
A trivial way is
Read the file line by line using getline().
Get the line into an istringstream.
Use istringstream as any istream like cin, it will only contain one line of text.
I would suggest you to search for these terms on some website like www.cppreference.com if you don't know them.

Skip last K lines while traversing a file [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
A user had posted a similar question earlier this day which was very soon closed due to its vagueness. Thus re-posting the question in detail with a solution as I didn't find a specific article dealing with it on the internet.
The requirement is to read and print all lines of a file except the last K.
Suppose a file contains text as:
Hello there!
My name is
Mr. XYZ
I like playing football
And if K is 2, then it should print all the lines except the last 2. i.e.:
Hello there!
My name is
Why not simply put lines into a std::deque and dump one element when its size is greater k ?
#include<iostream>
#include<fstream>
#include<deque>
int main()
{
std::fstream fs;
fs.open("output.txt",std::ios::in);
std::deque<std::string> deq;
std::string str;
int k=2;
while(std::getline(fs,str))
{
deq.push_back(str);
if(deq.size() > k)
{
std::cout <<deq.front()<<std::endl;
deq.pop_front();
}
}
}
This can easily be solved by creating a window of size K and then traversing the file till the right end of the window reaches the end of the file. The basic steps being:
Traverse the first K lines of the file without printing it.
Open the same file using another stream object.
Now simultaneously traverse both the streams so that fisrt stream is always K lines ahead of the second stream.
Run a loop while the second first stream is valid. In the loop, read through the first stream as well and keep print the lines.
The code would be
#include<iostream>
#include<fstream>
#include<string>
int main()
{
fstream fs;
fs.open("abc.txt",ios::in);
string str;
int K = 2;
while(getline(fs,str) && K>1)
{
K--;
}
if(K==1)
{
fstream fsNew;
fsNew.open("abc.txt",ios::in);
while(getline(fs,str))
{
getline(fsNew,str);
cout<<str;
}
}
cin.ignore();
}

Unknown reason behind out_of_range error for substring

UPDATE: Yes, answered and solved. I also then managed to find the issue with the output that was the real problem I was having. I had thought the substring error was behind it, but I was wrong, as when that had been fixed, the output issue persisted. I found that it was a simple mix up in the calculations. I had been subtracting 726 instead of 762. I could've had this done hours ago... Lulz. That's all I can say... Lulz.
I am teaching myself C++ (with the tutorial from their website). I have jumped ahead time to time when I have needed to do something I cannot with what I have learned so far. Additionally, I wrote this relatively quickly. So, if my code looks inelegant or otherwise unacceptable at a professional level, please do excuse that for now. My only current purpose is to get this question answered.
This program takes each line of a text file I have. Note that the text file's lines look like this:
.123.456.789
It has 366 lines. The program I first wrote to deal with this had me input each of the three numbers for each line manually. As I'm sure you can imagine, that was extremely inefficient. This program's purpose is to take each number out of the text file and perform functions and output the results to another text file. It does this per line until it reaches the end of the file.
I have read up more on what could cause this error, but I cannot find the cause of it in my case. Here is the bit of the code that I believe to contain the cause of the problem:
int main()
{
double a;
double b;
double c;
double d;
double e;
string search; //The string for lines fetched from the text file
string conversion;
string searcha; //Characters 1-3 of search are inserted to this string.
string searchb; //Characters 5-7 of search are inserted to this string.
string searchc; //Characters 9-11 of search are inserted to this string.
string subsearch; //Used with the substring to fetch individual characters.
string empty;
fstream convfil;
convfil.open("/home/user/Documents/MPrograms/filename.txt", ios::in);
if (convfil.is_open())
{
while (convfil.good())
{
getline(convfil,search); //Fetch line from text file
searcha = empty;
searchb = empty;
searchc = empty;
/*From here to the end seems to be the problem.
I provided code from the beginning of the program
to make sure that if I were erring earlier in the code,
someone would be able to catch that.*/
for (int i=1; i<4; ++i)
{
subsearch = search.substr(i,1);
searcha.insert(searcha.length(),subsearch);
a = atof(searcha.c_str());
}
for (int i=5; i<8; ++i)
{
subsearch = search.substr(i,1);
searchb.insert(searchb.length(),subsearch);
b = atof(searchb.c_str());
}
for (int i=9; i<search.length(); ++i)
{
subsearch = search.substr(i,1);
searchc.insert(searchc.length(),subsearch);
c = atof(searchc.c_str());
}
I usually teach myself how to get around these issues when they come up by looking at references and problems other people may have had, but I couldn't find anything that helped me in this instance. I have tried numerous variations upon this, but as the issue has something to do with the substring and I couldn't get rid of the substring in any of these variations, all returned the same error and the same result in the output file.
This is a problem:
while (convfil.good()) {
getline(convfil,search); //Fetch line from text file
You test for failure before you do the operation that can fail. When getline does fail, you're already inside the loop.
As a result, your code tries to process an invalid record at the end.
Instead try
while (getline(convfil,search)) { //Fetch line from text file
or even
while (getline(convfil,search) && search.length() > 9) {
which will also stop without error if there's a blank line at the end of the file.
It's possible you are reading a blank line at the end of the file and trying to process it.
Test for an empty string before processing it.

C++ Reading file using while loop, start at line "x"

I've been stuck on this issue for a while. What I have here is a loop that will read a text file containing file names. The loop reads these lines one by one, and sets it into memory via the variable sFileName. sFileName is later called upon to load an image, and the program does this one by one as the loop loads it. The user then selects a tag for the image and loads the next one. The tag and the image file name are exported into another text file, named imgresults.txt. Now, the text file with the file names is a few thousand lines. So, in the case that the user has to exit the program and tries to continue later, the loop restarts, instead of leaving off at the point when the program was closed.
I am trying to find a way to have the loop start at that point. So far, I decided to use getline() to count how many lines are currently in imgresults.txt, as that will give the number of images that have already been run through the program. This number is stored in the variable "x". I've been doing a lot of research, but I just cannot find how to set a condition for the while loop to begin at line "x". Do you guys have any suggestions? Also, if you need any clarifications, please ask. I only included the code regarding the loop, as the code for loading the image and such is perfect fine.
int _tmain(int argc, _TCHAR* argv[])
{
int value = 0;
int nCounter = 0;
FILE* fIn = NULL;
char * sLine = new char[MAX_FILENAME_SIZE];
char * sFileName = new char [MAX_FILENAME_SIZE];
char * s = new char [MAX_FILENAME_SIZE];
#define ImgListFileName "path"
#define ImgRepository "path"
if ((fIn = fopen(ImgListFileName,"rt"))==NULL)
{
printf("Failed to open file: %s\n",ImgListFileName);
return nCounter;
}
ifstream imgresults;
imgresults.open ("imgresults.txt");
int x=0;
string line;
while(!imgresults.eof()) {
getline (imgresults, line);
x++;
}
srand (time(NULL));
cout << x;
while(!feof(fIn)){
memset(sLine,0,MAX_FILENAME_SIZE*sizeof(char));
memset(sFileName,0,MAX_FILENAME_SIZE*sizeof(char));
memset(s,0,MAX_FILENAME_SIZE*sizeof(char));
fgets(sLine,MAX_FILENAME_SIZE,fIn);
strncpy(s,sLine,65);
strcat(sLine,"\0");
strcat(sFileName,s);
printf (sFileName);
nCounter++;
}
Thanks in advance!
If you really want to use imgresults.txt as the information on where you should start from the input file, then the best you can do is to have a while loop to read x lines from the input file just before the while loop where you read the input file.
while (x--) {
fgets(sLine, MAX_FILENAME_SIZE, fIn);
}
Better solution would probably be to write state of processing to another file so that you would not have to read input file line by line, but you could immediately seek to a known offset in the file.
Use ifstream::tellg to retrieve and store the current position of the file when the programm was closed.
Use ifstream::seekg to restore that position when the porgramm restarts.
Before you read each line, save the current offsets in your input and output file to a separate file, seeking back to the beginning and overwriting the existing data each time.
When/if you restart, read the offsets from that file, seek to those points, and start working from there.
You can just read lines in parallel from both files and stop when you reach the end of results file. When the loop ends, you have already discarded the file names that were already processed.
ifstream results("results.txt");
ifstream names("names.txt");
if (results && names) {
std::string temp1, temp2;
while (getline(results, temp1) && getline(names, temp2)) ; /* do nothing */
}
if (names) {
// process the rest
}
Not the most efficient solution, but it saves you the hassle of saving offsets. Just make sure that before the very first processing the results file is completely empty (or doesn't exist at all), otherwise this code will skip the first line of names file.

What is the easiest way to parse an INI File in C++? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm trying to parse an INI file using C++. Any tips on what is the best way to achieve this? Should I use the Windows API tools for INI file processing (with which I am totally unfamiliar), an open-source solution or attempt to parse it manually?
You can use the Windows API functions, such as GetPrivateProfileString() and GetPrivateProfileInt().
If you need a cross-platform solution, try Boost's Program Options library.
I have never parsed ini files, so I can't be too specific on this issue.
But i have one advice:
Don't reinvent the wheel as long as an existing one meets your requirements
http://en.wikipedia.org/wiki/INI_file#Accessing_INI_files
http://sdl-cfg.sourceforge.net/
http://sourceforge.net/projects/libini/
http://www.codeproject.com/KB/files/config-file-parser.aspx
Good luck :)
If you are already using Qt
QSettings my_settings("filename.ini", QSettings::IniFormat);
Then read a value
my_settings.value("GroupName/ValueName", <<DEFAULT_VAL>>).toInt()
There are a bunch of other converter that convert your INI values into both standard types and Qt types. See Qt documentation on QSettings for more information.
I use SimpleIni. It's cross-platform.
this question is a bit old, but I will post my answer. I have tested various INI classes (you can see them on my website) and I also use simpleIni because I want to work with INI files on both windows and winCE.
Window's GetPrivateProfileString() works only with the registry on winCE.
It is very easy to read with simpleIni. Here is an example:
#include "SimpleIni\SimpleIni.h"
CSimpleIniA ini;
ini.SetUnicode();
ini.LoadFile(FileName);
const char * pVal = ini.GetValue(section, entry, DefaultStr);
inih is a simple ini parser written in C, it comes with a C++ wrapper too. Example usage:
#include "INIReader.h"
INIReader reader("test.ini");
std::cout << "version="
<< reader.GetInteger("protocol", "version", -1) << ", name="
<< reader.Get("user", "name", "UNKNOWN") << ", active="
<< reader.GetBoolean("user", "active", true) << "\n";
The author has also a list of existing libraries here.
Have you tried libconfig; very JSON-like syntax. I prefer it over XML configuration files.
I ended up using inipp which is not mentioned in this thread.
https://github.com/mcmtroffaes/inipp
Was a MIT licensed header only implementation which was simple enough to add to a project and 4 lines to use.
If you are interested in platform portability, you can also try Boost.PropertyTree. It supports ini as persistancy format, though the property tree my be 1 level deep only.
Unless you plan on making the app cross-platform, using the Windows API calls would be the best way to go. Just ignore the note in the API documentation about being provided only for 16-bit app compatibility.
I know this question is very old, but I came upon it because I needed something cross platform for linux, win32... I wrote the function below, it is a single function that can parse INI files, hopefully others will find it useful.
rules & caveats:
buf to parse must be a NULL terminated string. Load your ini file into a char array string and call this function to parse it.
section names must have [] brackets around them, such as this [MySection], also values and sections must begin on a line without leading spaces. It will parse files with Windows \r\n or with Linux \n line endings. Comments should use # or // and begin at the top of the file, no comments should be mixed with INI entry data. Quotes and ticks are trimmed from both ends of the return string. Spaces are only trimmed if they are outside of the quote. Strings are not required to have quotes, and whitespaces are trimmed if quotes are missing. You can also extract numbers or other data, for example if you have a float just perform a atof(ret) on the ret buffer.
// -----note: no escape is nessesary for inner quotes or ticks-----
// -----------------------------example----------------------------
// [Entry2]
// Alignment = 1
// LightLvl=128
// Library = 5555
// StrValA = Inner "quoted" or 'quoted' strings are ok to use
// StrValB = "This a "quoted" or 'quoted' String Value"
// StrValC = 'This a "tick" or 'tick' String Value'
// StrValD = "Missing quote at end will still work
// StrValE = This is another "quote" example
// StrValF = " Spaces inside the quote are preserved "
// StrValG = This works too and spaces are trimmed away
// StrValH =
// ----------------------------------------------------------------
//12oClocker super lean and mean INI file parser (with section support)
//set section to 0 to disable section support
//returns TRUE if we were able to extract a string into ret value
//NextSection is a char* pointer, will be set to zero if no next section is found
//will be set to pointer of next section if it was found.
//use it like this... char* NextSection = 0; GrabIniValue(X,X,X,X,X,&NextSection);
//buf is data to parse, ret is the user supplied return buffer
BOOL GrabIniValue(char* buf, const char* section, const char* valname, char* ret, int retbuflen, char** NextSection)
{
if(!buf){*ret=0; return FALSE;}
char* s = buf; //search starts at "s" pointer
char* e = 0; //end of section pointer
//find section
if(section)
{
int L = strlen(section);
SearchAgain1:
s = strstr(s,section); if(!s){*ret=0; return FALSE;} //find section
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain1;} //section must be at begining of a line!
s+=L; //found section, skip past section name
while(*s!='\n'){s++;} s++; //spin until next line, s is now begining of section data
e = strstr(s,"\n["); //find begining of next section or end of file
if(e){*e=0;} //if we found begining of next section, null the \n so we don't search past section
if(NextSection) //user passed in a NextSection pointer
{ if(e){*NextSection=(e+1);}else{*NextSection=0;} } //set pointer to next section
}
//restore char at end of section, ret=empty_string, return FALSE
#define RESTORE_E if(e){*e='\n';}
#define SAFE_RETURN RESTORE_E; (*ret)=0; return FALSE
//find valname
int L = strlen(valname);
SearchAgain2:
s = strstr(s,valname); if(!s){SAFE_RETURN;} //find valname
if(s > buf && (*(s-1))!='\n'){s+=L; goto SearchAgain2;} //valname must be at begining of a line!
s+=L; //found valname match, skip past it
while(*s==' ' || *s == '\t'){s++;} //skip spaces and tabs
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
if(*s != '='){goto SearchAgain2;} //no equal sign found after valname, search again
s++; //skip past the equal sign
while(*s==' ' || *s=='\t'){s++;} //skip spaces and tabs
while(*s=='\"' || *s=='\''){s++;} //skip past quotes and ticks
if(!(*s)){SAFE_RETURN;} //if NULL encounted do safe return
char* E = s; //s is now the begining of the valname data
while(*E!='\r' && *E!='\n' && *E!=0){E++;} E--; //find end of line or end of string, then backup 1 char
while(E > s && (*E==' ' || *E=='\t')){E--;} //move backwards past spaces and tabs
while(E > s && (*E=='\"' || *E=='\'')){E--;} //move backwards past quotes and ticks
L = E-s+1; //length of string to extract NOT including NULL
if(L<1 || L+1 > retbuflen){SAFE_RETURN;} //empty string or buffer size too small
strncpy(ret,s,L); //copy the string
ret[L]=0; //null last char on return buffer
RESTORE_E;
return TRUE;
#undef RESTORE_E
#undef SAFE_RETURN
}
How to use... example....
char sFileData[] = "[MySection]\r\n"
"MyValue1 = 123\r\n"
"MyValue2 = 456\r\n"
"MyValue3 = 789\r\n"
"\r\n"
"[MySection]\r\n"
"MyValue1 = Hello1\r\n"
"MyValue2 = Hello2\r\n"
"MyValue3 = Hello3\r\n"
"\r\n";
char str[256];
char* sSec = sFileData;
char secName[] = "[MySection]"; //we support sections with same name
while(sSec)//while we have a valid sNextSec
{
//print values of the sections
char* next=0;//in case we dont have any sucessful grabs
if(GrabIniValue(sSec,secName,"MyValue1",str,sizeof(str),&next)) { printf("MyValue1 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue2",str,sizeof(str),0)) { printf("MyValue2 = [%s]\n",str); }
if(GrabIniValue(sSec,secName,"MyValue3",str,sizeof(str),0)) { printf("MyValue3 = [%s]\n",str); }
printf("\n");
sSec = next; //parse next section, next will be null if no more sections to parse
}
Maybe a late answer..But, worth knowing options..If you need a cross-platform solution , definitely you can try GLIB,, its interesting.. (https://developer.gnome.org/glib/stable/glib-Key-value-file-parser.html)