Program To Input/Output File And Find String - string

Beginner C++ student here, first ever programming class. Currently learning string functions and input/output files. Trying to put a program together which will look at an existing file for the name 'john' or 'JOHN' in both upper and lower case. Then output the results into another file.
We were told we could convert all instances of the name to upper or lower case (I chose upper) so the the program would output instances of the name regardless what case it is in.
I noted below where I am having one of my problems and I may have more somewhere else which I can't see yet. Wondering if any of you kind folks can help me out with this.
Below is what I have so far and I noted the errors being returned as well.
Thank you so very much for your time and help!!!
#include <fstream>
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
bool die(const string & msg);
bool input(string & s, const string & prompt);
bool open(ifstream & fin, const string & fileName);
bool open(ofstream & fout, const string & fileName);
//bool name(const string & line);
bool convert(string & str, string & converted);
int main() {
string inName, outName;
ifstream fin;
ofstream fout;
if (!input(inName, "Name of input file: "))
die("I can't read the name of the input file");
if (!open(fin, inName))
die("I can't open " + inName + " for output");
if (!input(outName, "Name of output file: "))
die("I can't read the name of the input file");
if (!open(fout, outName))
die("I can't open " + outName + " for output");
for (string converted; getline(fin, converted);) {
if (convert(converted)) //<---***HAVING AN ISSUE HERE***
fout << converted << endl;
}
if (fin.rdstate() != (ios::failbit | ios::eofbit))
die("Input file " + inName + " terminated input incorrectly");
fout.close();
if (!fout)
die("Output file " + outName + "had a problem with writing or closing");
fin.close();
cout << "read from " << inName << ", wrote to " << outName << ", ok" << endl;
}// main
bool die(const string & msg){
cout << "Fatal error: " << msg << endl;
exit(EXIT_FAILURE);
}
bool input(string & s, const string & prompt) {
cout << prompt;
return getline(cin, s) ? true : false;
}
bool open(ifstream & fin, const string & fileName){
fin.open(fileName);
return fin ? true : false;
}
bool open(ofstream & fout, const string & fileName){
ifstream tin(fileName);
if (tin) return false;
fout.open(fileName);
return fout ? true : false;
}
//bool name(const string & line){
//return line.find("john") != UINT_MAX;
//}
bool convert(string & str, string & converted)
{
for (short i = 0; i < str.size(); ++i)
converted += toupper(str[i]);
return converted.find("john") != UINT_MAX;
}
Errors I am getting:
Error 1 error C2660: 'convert' : function does not take 1 arguments Line 40
Warning 2 warning C4018: '<' : signed/unsigned mismatch Line 93
3 IntelliSense: too few arguments in function call Line 40

Well, the error message pretty much says it all. The convert function is declared to take two arguments, but you're only passing in one argument.
bool convert(string & str, string & converted)
You need to pass another string reference that takes the converted string.
Off topic: Also, for the sake of security (and maybe you later wanting to switch to other programming languages): Please don't start learning the bad habit of considering everything not 0 to be true.
Things like the following are bound to cause trouble sooner or later:
return fin ? true : false;

Related

std::string::find returns npos when the char is present in the string

In a small utility I'm writing, I want to read a file record and:
look for the presence of an XOR checksum in the form *XX, where XX are hex digits
replace it if it's incorrect
add one if it's not present
So far, I'm only to the point of reading the file and looking for the checksum. The problem I'm up against is that std::string::find is not finding the * I know to be present; it returns npos every time.
The find() is on line 37. The first line read into strInput is:
$GPGGA,14240.99,2732.581,S,15301.947,E,1,06,3,65,M,37,M,-1.0,0006*6E\n
Here's the code:
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter input file name:\n";
std::string strFileName = "";
std::getline(std::cin, strFileName);
std::cout << "Filename entered: " << strFileName << '\n';
FILE* fp;
int nErrCode = EXIT_FAILURE;
fopen_s(&fp, strFileName.c_str(), "r+");
if (!fp)
{
std::string strErr = "Failed to open " + strFileName;
perror(strErr.c_str());
return nErrCode;
}
rewind(fp);
std::string strInput;
strInput.reserve(100);
std::string::size_type n;
do
{
fgets(&strInput[0], 99, fp);
std::cout << strInput.c_str();
//n = 0;
n = strInput.find('*');
if (n != std::string::npos)
std::cout << "Found checksum at position " << n;
else
std::cout << "Did not find checksum";
} while (!feof(fp));
}
Thanks in advance.
I've debugged this and all is well up to the find(). At that point, I can see that the return value is npos, even though I can see the value of strInput and verify that it contains an asterisk.

AppCenter: Find and replace string in a file during build

Is it possible to edit a .mm file before it gets compiled in AppCenter?
In an attempt to fix a build error, I want to find and replace a string in ../node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm.
I tried using sed -i 's/oldString/newString/g' ../node_modules/react-native/React/CxxBridge/RCTCxxBridge.mm inside appcenter-pre-build.sh but it does not work.
Any help will be appreciated,
Thanks.
Not sure if this is your case, but I needed to update a version number on a complex project. To replace the counter of the current version with a new one, I considered updating the file with each build. After some versions of bash scripts, I realized that it's easier for me to write a console application in C with a couple of parameters to solve this problem. Works almost perfect for me. If you need I can share the simple code of this program.
Here is the C code that looks for a string in the file passed as a parameter and replaces the version number in it.
int main(int argc, char* argv[])
{
cout << "Version changer start\n";
if (argc < 2) {
cout << "There is no path argument. Version was no changed.";
return 1;
}
string sourcePath = argv[1];
string targetPath = sourcePath + ".tmp";
bool firstLine = true;
cout << sourcePath << endl;
ifstream sourceFile(sourcePath); // open file for input
ofstream targetFile(targetPath); // open file for output
string line;
while (getline(sourceFile, line)) // for each line read from the file
{
// looking for the desired line
if (line.find("public static String VER") != std::string::npos) { // replace "public static String VER" to your string definition code
line.replace(0, 32, "");
line.replace(line.length() - 2, 2, "");
int number = atoi(line.c_str());
number++; // In my case, I get an integer and add one to it
string v = to_string(number);
line = " public static String VER = \"" + v + "\";";
cout << v;
}
if (firstLine) {
targetFile << line;
firstLine = false;
}
else
targetFile << endl << line;
}
sourceFile.close();
targetFile.close();
remove(sourcePath.c_str());
if (rename(targetPath.c_str(), sourcePath.c_str()) != 0)
perror("Error renaming file");
else
cout << endl << "----------- done -----------\n";
}

No suitable constructor exists to convert from "char" to "std::string"

I'm new to coding in C and C++, and I have a program with
an issue. When I (try) to run it, it gives me this error:
"No suitable constructor exists to convert from "char" to "std::string".
I'm not sure what it means. My code is an example of a simple
substitution cipher covered in the book "Cracking Codes with Python" by Al Sweigart.
I just want to replicate it in C++. Here's my code:
#include <iostream> // for communicating with user
#include <string>
using namespace std;
string symbols = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // all symbols
string encrypt(string msg, string key, string mode) {
string ca = symbols;
string cb = key;
string translated;
if (mode == "decrypt") {
ca, cb = cb, ca;
}
int index = 0;
for (index = 0; index < msg.length(); index++) {
cout << "index is " << index << endl;
int sindex = ca.find(msg[index]); // it works here
cout << "sindex is " << sindex << endl;
string cl = cb[sindex]; // the problem
translated += cl;
}
return translated;
}
int main() {
string msg = "";
string key = "";
string mode = "";
string ciphertext = ""; // our variables
cout << "Enter message: (no spaces please)\n";
cin >> msg;
cout << "Enter key (or \"none\" for using default):\n";
cin >> key;
if (key == "none") {
key = "QWERTYUIOPASDFGHJKLZXCVBNM";
}
cout << "Enter mode: (\"encrypt\" or \"decrypt\")\n";
cin >> mode;
ciphertext = encrypt(msg, key, mode);
cout << "The ciphertext is\n" << ciphertext;
}
For some reason it works with msg on line 17 but not with cb on line 19, even though
they're both std::string. The actual error is on line 19 with string cl = cb[sindex];.
Not even sure what's wrong. It works on line 17 int sindex = ca.find(/*The thing here*/msg[index]);.
(Maybe my Visual Studio 2019 has gone nuts.) If I replace cb with msg it still gives me the
same error. Maybe line 17 is a lucky line? Who knows? But please help, I'm so
confused!

Do while loop won't break

I am making a Goldilocks game. If the user chooses the wrong answer it would loop back to the beginning of the program. When I try to choose any option it always loops back to the beginning including the correct answer which is 2. I am still new to c++. I do not understand why it is looping to the beginning if the condition is true when 2 is chosen.
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
void FirstSet()
{
bool win = false;
string PName;
int choice;
int num1, num2, result;
do
{
system("CLS");
cout << " Please Enter Name \n";
cin >> PName;
cout << PName << " and the Three Bears\n\n ";
cout << PName << " Walks up and sees 3 Doors, 1 Large Door, 1 Medium
Door and 1 Small Door. \n\n\n " << "Which Door do you want to Open?\n "
<< " 1 for The Large Door\n " << " 2 for the Medium Door\n " << " 3
for the small door\n ";
cin >> choice;
if (choice == '1')
{
cout << " The large door is too heavy it will not budge.\n "
<< " Please Try Again\n\n ";
system("pause");
}
else if (choice == '2')
{
win = true;
}
else if (choice == '3') {
cout << " The Door is too small you would get stuck.\n "
<< "Please Try Again\n\n";
}
} while (!win);
}
int main()
{
FirstSet();
system("pause");
return 0;`
The reason none of your comparisons are turning true is because you are reading the input into an int variable. Then you are comparing to ascii character values of 1,2 and 3 which happen to be 49, 50 and 51 respectively. If you modify your if lines to compare directly with integers, it should work:
if (choice == 1)
{
...
}
else if (choice == 2)
{
...
}
else if (choice == 3)
{
...
}
Although, for readability purposes and also to avoid such cases, I recommend using switch case statements in this case.

c++ program of sorting names

Instruction for program:
Read the list of names from “names.txt” in the format “First Last”.
Sort the names based upon typical alphabetic order of peoples names based upon last name then first name.
Write the sorted list to a file called “sortednames.txt” in the format “Last, First”.
Here's my code: file data was stored in fullname array but now I am stuck on how to flip the first and last name in the array??
int main()
{
const int MAXNAMES = 100;
int value = 0;
string fullname[MAXNAMES];
ifstream inFile;
inFile.open("names.txt"); //open the file to excess the rainfall data
if (inFile.fail()) // testing the file
{
cout << "Error opening file. Please check that the file currently `enter code here`exist" << endl;
exit(1);
}
cout << "File successfully open" << endl;
while(!inFile.eof())
{
while(value < 100)
{
getline(inFile,fullname[value]);
value++;
}
}
return 0;
}
To flip the name around you could do the following:
string myString;
int spacePosition;
value = 0;
while(value < 100) {
myString = fullname[value];
spacePosition = myString.find(" ");
fullname[value] = myString.substr(spacePostion) + " " + myString.substr(0, spacePostion -1);
}

Resources