I write this C++ program, destinated to reproduce the echo command :
#include <iostream>
#include <queue>
#include <string>
#include <iterator>
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[])
{
//Step 1: convert a silly char*[] to queue<string>
queue<string> args;
for(int i=1;i<=argc;i++)
{
args.push(string(argv[i]));
}
//Step 2: Use this queue<string> (because a non-used variable, that's useless)
string arg, var, tos;
bool showEndl = true;
for(int i=0;i<=argc;i++) //The implementation of for arg in args is so crazy
{
arg = args.front(); //I can do arg = args[i] but that's not for nothing I make a queue. The cashier, she takes the customer front, she does not count the number of customers.
args.pop(); //Pop the arg
if(arg[0] == '$') //If that's a variable
{
var = ""; //Reset the variable 'var' to ''
for(string::iterator it=arg.begin();it!=arg.end();it++) //Because C++ is so complicated. In Python, that's just var = arg[1:]
{
var += *it;
}
tos += string(getenv(var.c_str()));
tos += ' ';
}
else if(arg == "-n") //Elif... No, C++ do not contains elif... Else if this is the -n argument.
{
showEndl = false;
}
else
{
tos += arg;
tos += ' ';
}
}
//Step 3 : Show the TO Show string. So easy.
cout << tos;
//Step 4 : Never forget the endl
if(showEndl)
{
cout << endl;
}
string a;
}
It compiles fine, but when I run it, it tells me "Segmentation fault: 11" in the console.
I use LLVM. What that means? Why that makes that?
PS : I use LLVM.
The segmentation fault is due to memory access violation - dereferencing invalid pointer:
for( int i = 1; i <= argc; i++)
{
args.push( string( argv[ i]));
}
When there are argc arguments sent to a program the last one is indexed with argc - 1.
for( int i = 0; i < argc; i++) // includes also a name of a program, argv[ 0]
{
args.push( string( argv[ i]));
}
or:
for( int i = 1; i < argc; i++) // excludes a name of a program, argv[ 0]
{
args.push( string( argv[ i]));
}
I suggest a use of debuger. It will show you the line causing a fault so you can investigate invalid pointer.
Change also to:
for( int i=0; i < args.size(); ++i)
{
arg = args.front();
Related
So writing a palindrome with pointers and boolean. I have it working with a single word but then I began building it to work with a sentence. The problem is I am unsure how to keep the new modified sentence after making it lowercase and getting rid of the spaces for it to return whether it is or isn't a palindrome. It keeps returning the palindrome as false and when I went to check why I see that the program ignores the modification and kept the original string. I can't use "&" on the parameter as I tested it out. Any hints or takes on what I can do to keep the new modified string?
int main()
{
userInput();
return 0;
}
void userInput()
{
char str[90];
std::cout<<"Please enter a string to check if it is a palindrome: ";
std::cin.getline(str, 90);
modifyString(str);
}
void modifyString(char *string)
{
int count = 0;
for (int i=0; i<strlen(string); i++)
{
putchar(tolower(string[i]));
}
for (int i = 0; string[i]; i++)
{
if (string[i] != ' ')
{
string[count++] = string[i];
}
}
string[count] = '\0';
std::cout<<string<<std::endl;
results(string);
}
bool checkPalindrome(char *string)
{
char *begin;
char *end;
begin = string;
end = (string + strlen(string)-1);
while(begin != end)
{
if ((*begin) == (*end))
{
begin ++;
end--;
}
else
{
return false;
}
}
return true;
}
void results(char *string)
{
bool isItPalindrome;
isItPalindrome = checkPalindrome(string);
if( isItPalindrome == true)
{
std::cout<<"\nCongrats, the string is a palindrome!";
}
else
{
std::cout<<"\nThis string is not a palindrome.";
}
}
For starters this definition of main
int main()
{
userInput();
return 0;
}
does not make a sense. According to the function name main the function should perform the main task that is to output whether the entered sentence is a palindrome or not.
This for loop
for (int i=0; i<strlen(string); i++)
{
putchar(tolower(string[i]));
}
does nothing useful. It just outputs the string in the lower case.
This statement
end = (string + strlen(string)-1);
can invoke undefined behavior if an empty string was passed.
This while loop
while(begin != end)
{
if ((*begin) == (*end))
{
begin ++;
end--;
}
else
{
return false;
}
}
also can invoke undefined behavior for a string containing an even number ofo characters because after this if statement
if ((*begin) == (*end))
{
begin ++;
end--;
}
if the two adjacent characters are equal then begin after incrementing will be greater than end after its decrementing. And as a result the loop will continue its iteration.
In general the approach when the original string is changed is just a bad approach.
Your program has too many functions. It is enough to write one function that will determine whether the passed string is a palindrome or not.
Here is a demonstrative program.
#include <iostream>
#include <cstring>
#include <cctype>
bool checkPalindrome( const char *s )
{
const char *t = s + std::strlen( s );
do
{
while ( s != t && std::isspace( ( unsigned char )*s ) ) ++ s;
while ( s != t && std::isspace( ( unsigned char )*--t ) );
} while ( s != t &&
std::tolower( ( unsigned char )*s ) == tolower( ( unsigned char ) *t ) &&
++s != t );
return s == t;
}
int main()
{
const size_t N = 100;
char s[N] = "";
std::cout << "Please enter a string to check if it is a palindrome: ";
std::cin.getline( s, N );
std::cout << '\n';
if ( checkPalindrome( s ) )
{
std::cout << "Congrats, the string is a palindrome!\n";
}
else
{
std::cout << "This string is not a palindrome.\n";
}
return 0;
}
Its output might look like
Please enter a string to check if it is a palindrome: 1 23 456 6 54 321
Congrats, the string is a palindrome!
Okay, I solved it!
As one of the users on here brought up a point that my lowercase did not modify the string and only prints it out. I try my best to solve the problem and I think I found the solution and everything works perfectly fine. comment back to debug it if you like to see how it looks but what I did was create a for loop again for the lower case but made another pointer with it. here how it looks.
for (char *pt = string; *pt != '\0'; ++pt)
{
*pt = std::tolower(*pt);
++pt;
}
Now that definitely changes the string into a lower case and keeps it as a lower case.
so now the modified function looks like this and ready to take any sentence palindrome you give it. Example: A nUt fOr a jAr of tUNa. We make this all lowercase and take out space and boom palindrome and return true.
void modifyString(char *string)
{
int count = 0;
for (char *pt = string; *pt != '\0'; ++pt)
{
*pt = std::tolower(*pt);
++pt;
}
for (int i = 0; string[i]; i++)
{
if (string[i] != ' ')
{
string[count++] = string[i];
}
}
string[count] = '\0';
//take out the forward slash below to see how it looks after being modified
// std::cout<<std::endl<<string<<std::endl;
results(string);
}
Why is this program returning garbage values? I expect the output to be the word 'large', but the value is actually 'rat' - the last word.
#include <iostream>
#include <string>
using namespace std;
std::string LongestWord(std::string sen)
{
std::string s2, lW;
for (int i = 0; i < sen.size(); ++i) {
while (sen[i] != ' ') {
s2 += sen[i];
++i;
}
if (s2.size() > lW.size()) {
lW = ""; lW = s2;
}
s2 = "";
}
return lW;
}
int main(void)
{
cout << LongestWord("a cat ate the large rat") << endl;
return 0;
}
Your internal while loop will almost certainly run beyond the end of the given string argument (unless it has a space at the end). Change this internal loop to check for the size of that string, as follows:
while (i < sen.size() && sen[i] != ' ') {
s2 += sen[i];
++i;
}
I have a C++ project that was previously receiving multiple command line arguments with code like so:
int main(int argc, char *argv[]) {
for (int i = 1; i < 4; i = i + 1) {
// do some stuff with argv[i]
int in_arg = m[argv[i]];
}
return 0
}
Using this code, an example command line argument might be:
C:\MyFolder\MyExecutable.exe 4 0 1
However, due to plugging this code into a wider project my command line will now have to look like this instead:
C:\MyFolder\MyExecutable.exe 401
How can I split the argument 401 into a vector or similar that is functionally the same as having three input arguments like 4 0 1 so that my line:
int in_arg = argv[i];
...could be repointed to something like:
int in_arg = new_vector[i];
I only dabble with C++, so apologies if I am asking basic questions.
Thanks
If you already know that the 1st argument is the one to use it's simple, copy it to a string and then access it using one of the iteration options given by C++, I'm using a foreach type cycle:
#include <iostream>
#include <vector>
int main(int argc, char** argv)
{
if(argc < 2){
std::cout << "Not enough arguments"; //<-- args check
return 0;
}
std::string s1;
s1 = argv[1]; //<-- copy argument to a string type to use string iterator
std::vector<int> args_vector;
for (char c : s1) {
args_vector.push_back(c - '0'); // convert char to integer and save it in vector
}
for(int i: args_vector){ // print the args in integer format, 1 by 1
std::cout << i << " ";
}
return 0;
}
You could create strings out of the arguments and just go though them character by character:
#include <iostream>
#include <string>
#include <vector>
int cppmain(std::string program, std::vector<std::string> args) {
std::cout << program << " got " << args.size() << " argument(s):\n";
for(auto& arg : args) { // each argument as a string
std::cout << " " << arg << '\n';
for(char ch : arg) { // each char in the current argument
if(ch < 0) continue; // skip negative char:s
int in_arg = m[ch]; // assuming it was: int in_arg = m[*argv[i]];
// use in_arg
}
}
return 0;
}
int main(int argc, char* argv[]) {
//
// string from char*
// |
// V
return cppmain(argv[0], {argv + 1, argv + argc});
// ^ ^
// | |
// vector<string> from char*[]
}
I am having trouble figuring out the process to add a space in a string at capital letters in C++. If I have a string "HelloWorld", how do I convert that to "Hello World"?
I've tried using substrings and the isupper function but I can't get anything to work.
Edit: this is the code I have. I don't understand why in = newname is not valid code.
string breakStringAtCaps(string in) {
string newname[10];
int j = 0;
for (int i = 0; i < in.size(); i++) {
if (isupper(in[i]) && i != 0) {
newname[j] = " ";
j++;
}
newname[j] = in[i];
j++;
}
in = newname;
return in;
}
You can do it like this:
string breakStringAtCaps(const string& in)
{
string newname;
for(int i = 0; i < in.size(); i++)
{
if(isupper(in[i]) && i != 0)
newname += " ";
newname += in[i];
}
return newname;
}
You are thinking right in thinking substr, but you implementation is a bit off. If creating an new string containing the contents of the original and inserting a ' ' (space) before each upper-case letter (not including the first), you can seed the new string with the first character of the original using substr(0,1) and then use an auto ranged for loop and substr(1) to evaluate each character after the first.
The loop along with a check of isupper() is basically all you need, e.g.
#include <iostream>
#include <string>
#include <cctype>
int main (int argc, char **argv) {
std::string s = argc > 1 ? argv[1] : "HelloWorld",
snew = s.substr (0,1);
if (s.size() > 0)
for (auto& c : s.substr(1)) {
if (std::isupper (c))
snew += " ";
snew += c;
}
std::cout << snew << '\n';
}
(the program will use "HelloWorld" by default if no string is given as an argument on the command line, otherwise the string given on the command line is used)
Example Use/Output
$ ./bin/spacebeforeupper
Hello World
Or with a string given as an argument:
$ ./bin/spacebeforeupper MyDogHasFleas
My Dog Has Fleas
You can iterate through the strin characters, check if it is a cap and insert a ' ' before if it is one:
It should look like:
for(int i=0; i < str.length(); i++)
{
if (str[i]>='A' && str[i]<='Z')
{
if (i != 0)
cout << " ";
cout << str[i];
}
else
{
cout << str[i];
}
}
I just give a implementation, maybe not the best solution:
#include <string>
#include <ctype.h>
void breakStringAtCaps(std::string& in) {
std::string::const_iterator it = in.begin();
while(it != in.end()) {
if(it != in.begin() && isupper(*it)) {
in.insert(it, ' ');
it += 2;
}
else
++it;
}
}
//
#include <iostream>
int main(int argc, char** argv) {
std::string str("HelloWorld;");
breakStringAtCaps(str);
std::cout << str.c_str() << std::endl;
return 0;
}
and in your code,
string newname[10];
here 'newname' is a string array's name. you should not assign the name of array to a string instance.
and newname[i] means the i-th string of the array, not the i-th char of a string named 'newname' as you desired.
It's supposed to look like this: http://i.imgur.com/gko501E.png
Instead it looks like this: http://i.imgur.com/ISwqyD8.png
When I take the code out of the function and use it in the main class it works properly. However once I put it in this function the formatting problems occur, it also isn't filtering like it's supposed to. This program is supposed to take user input, store it in a string, remove all non-alphabetical characters, capitalize the vowels, and then space it out based on user defined variables given in the command line. It's also supposed to accept files as input in the command line, such as: 'program 5 8 < file'.
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <cstdlib>
#include <fstream>
#include <sstream>
using namespace std;
//make vowels uppercase
string filter(string input)
{
size_t found = input.find_first_of("aeiou");
while (found != string::npos)
{
if (islower(input[found]))
{
input[found] = toupper(input[found]);
found = input.find_first_of("aeiou", found + 1);
}
}
//Make consonants lowercase
size_t foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ");
while (foundLower != string::npos)
{
if (isupper(input[foundLower]))
{
input[foundLower] = tolower(input[foundLower]);
foundLower = input.find_first_of("BCDFGHJKLMNPQRSTVWXYZ", foundLower + 1);
}
}
//remove punctuation
for (int i = 0, len = input.size(); i < len; i++)
{
if (!isalnum(input[i]))
{
input.erase(i--, 1);
len = input.size();
}
}
return input;
}
int main(int argc, char* argv[])
{
int wordSize;
int wordSizeCounter;
int wordCounter = 0;
int rowSize;
//char letter;
wordSize = atoi(argv[1]);
rowSize = atoi(argv[2]);
ifstream inFile;
inFile.open(argv[3]);//open the input file
stringstream strStream;
strStream << inFile.rdbuf();//read the file
string test = strStream.str();//str holds the content of the file
if (!inFile) test = cin.get() ; // Read first character
//Begin filter for files
while (!test.empty())
{
filter(test);
if (test.length() < wordSize) //make sure we don't go out-of-bounds
{
wordSize = test.length();
}
cout << test.substr(0, wordSize);
cout << " ";
if (test.length() >= wordSize) //again, make sure we don't go out-of-bounds
{
test = test.substr(wordSize);
}
else
{
test = " ";
}
wordCounter++;
if (wordCounter == rowSize)
{
cout << std::endl;
wordCounter = 0;
}
if(test.empty())
{
test = cin.get();
}
}
cout << endl;
return 0;
}