I've been trying to run a program that will invert the order of a string and to run it, I have to type a second argument in prompt.
int main(int argc, char* argv[])
{
string text = argv[2];
for (int num=text.size(); num>0; num--)
{
cout << text.at(num);
}
return 0;
}
e.g. ./program lorem result: merol
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
string text = argv[1];
for (int num=text.size() - 1; num >= 0; num--)
{
cout << text.at(num);
}
return 0;
}
You missed the includes and used string::at wrong. There are size() chars in the string but you start counting at 0. Then the loop has to run until num >= 0 and not num > 0. You also used the wrong index into argv.
This would still be an abomination of C++. A clearer way would be:
#include <iostream>
#include <string>
#include <algorithm>
int main(int argc, char* argv[])
{
std::string text = argv[1];
for(std::string::reverse_iterator it = text.rbegin(); it != text.rend(); ++it) {
std::cout << *it;
}
std::cout << std::endl;
//or if you want further usage of the reversed string
std::reverse(text.begin(), text.end());
std::cout << text;
return 0;
}
I think you're getting an exception because num is out of bounds. size() is returning a value one larger than the biggest valid index into the string, so at() is throwing an exception.
Related
I'm doing a leetcode challenge to practice my c++
I am supposed to replace all the "." from an ip address to "[.]"
so essentially, x.x.x.x is supposed to become x[.]x[.]x[.]x
My code is :
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, const char * argv[]) {
string address ="1.1.1.1";
while(address.find(".") != string::npos){
address.replace(address.find("."), 1,"[.]");
}
cout<<address<<endl;
}
However, I am getting stuck in a loop where it is doing :
x.x.x.x
x[.]x.x.x
x[[.]]x.x.x
x[[[.]]]x.x.x
and so on.
How do I get out of this loop? Thank you!
You can specify where to start by the 2nd argument of std::string::find.
#include <iostream>
#include <string>
int main(int argc, const char * argv[]) {
std::string address ="1.1.1.1";
std::string::size_type start_pos = 0, current_pos;
while((current_pos = address.find(".", start_pos)) != std::string::npos){
address.replace(current_pos, 1,"[.]");
start_pos = current_pos + 3; // start next search after the inserted string
}
std::cout<<address<<std::endl;
}
Learn to separate code into functions (this is important). Also it is easier to store result into separate variable, so you do not have to update search point.
std::string escapeDots(const std::string& s)
{
std::string result;
result.reserve(s.size() + 8);
for (auto ch : s) {
if (ch == '.')
result += "[.]";
else
result += ch;
}
return result;
}
This code is more clear the alternative answer and most probably is faster.
With <regex>, it would be
int main()
{
std::string address = "1.1.1.1";
std::cout << std::regex_replace(address, std::regex("\\."), "[.]") << std::endl;
}
Demo.
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*[]
}
#include<fstream>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
for (int i=1; i<argc ; i++)
{
cout<< argv[i]<< endl;
if( argv[i] == 'all')
cout<<"hey"<< endl;
}
i am passing "1 all emptyfile" through the command files. but i want to compare when argue[i] is equal to all, i want it to print hey
i get this error "Comparison between pointer and integer ('char *' and 'int')" at the if( argv[i] == 'all') anyway i could do it ?
C-style strings can't be compared directly, and even worse, 'all' isn't a string (you probably meant "all", note the quotes).
The C-way to compare them is to use strcmp:
#include <cstring>
if (std::strcmp(argv[i], "all") == 0) { ... }
Since you are using C++, you can use std::string which will allow you to compare strings directly.
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
string s = "all";
for (int i=1; i<argc ; i++)
{
cout<< argv[i]<< endl;
if( argv[i] == s)
cout<<"hey"<< endl;
}
}
Note: all is in double-quotes.
Output when you run the program:
>a.exe all
all
hey
I need to save all arguments to a vector or something like this. I'm not a programmer, so I don't know how to do it, but here's what I've got so far. I just want to call a function system to pass all arguments after.
#include "stdafx.h"
#include "iostream"
#include "vector"
#include <string>
using namespace std;
int main ( int argc, char *argv[] )
{
for (int i=1; i<argc; i++)
{
if(strcmp(argv[i], "/all /renew") == 0)
{
system("\"\"c:\\program files\\internet explorer\\iexplore.exe\" \"www.stackoverflow.com\"\"");
}
else
system("c:\\windows\\system32\\ipconfig.exe"+**All Argv**);
}
return 0;
}
i need to save all arguments to a vector or something
You can use the range constructor of the vector and pass appropriate iterators:
std::vector<std::string> arguments(argv + 1, argv + argc);
Not 100% sure if that's what you were asking. If not, clarify.
To build string with all argument concatenated and then run a command based on those arguments, you can use something like:
#include <string>
using namespace std;
string concatenate ( int argc, char* argv[] )
{
if (argc < 1) {
return "";
}
string result(argv[0]);
for (int i=1; i < argc; ++i) {
result += " ";
result += argv[i];
}
return result;
}
int main ( int argc, char* argv[] )
{
const string arguments = concatenate(argc-1, argv+1);
if (arguments == "/all /renew") {
const string program = "c:\\windows\\system32\\ipconfig.exe";
const string command = program + " " + arguments;
system(command.c_str());
} else {
system("\"\"c:\\program files\\internet explorer\\iexplore.exe\" \"www.stackoverflow.com\"\"");
}
}
Why cant i call string.find in string.erase like so: str.erase(str.find(a[1]),str.size())?
edit:code added
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// html tags
string tags[5]={"<!--...-->","<!DOCTYPE>","<a>","<abbr>","<acronym>"};
//
//check if string exists
int boolStringExists(string a, string b)
{
if(a.find(b)>0)
{
return 1;
}
if(a.find(b)<=0)
{
return 0;
}
}
//erase tag from string a
void eraseTags(string a,string b[])
{
for(int i=0; i<5;i++)
{
int x=(boolStringExists(a,b[i]));
while (x>0)
{
a.erase(a.find(b[i]),b[i].size());
x=(boolStringExists(a,b[i]));
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
fstream file;
file.open("h:\\a.htm");
string k,m;
while(getline(file, k))
m += k ;
eraseTags(m,tags);
return 0;
}
Gives this message: "this application has requested the runtime to terminate it in an unusual way.Please contact the application's support team for more information."
If the string is not found, find returns string::npos, and then your code wouldn't work and will give runtime error. See this gives error : https://ideone.com/NEhqn
So better write this:
size_t pos = str.find(a[1]);
if ( pos != std::string::npos)
str.erase(pos); //str.size() is not needed!
Now this doesn't give error : https://ideone.com/IF2Hy
There's nothing wrong with that call (assuming a[1] exists and is found in str at least once)
#include <iostream>
#include <string>
int main()
{
std::string str = "Hello, world!";
std::string a = "wwwwww";
str.erase(str.find(a[1]), str.size());
std::cout << str << '\n';
}
test run: https://ideone.com/8wibR
EDIT: Your full source code fails to check if b[1] is actually found in str. The function boolStringExists() returns 1 if a.find(b) is greater than zero, and the value of std::string::npos which it returns when b is not found in a IS greater than zero.
To fix this while keeping the rest of your logic intact, change that function to
//check if string exists
bool boolStringExists(string a, string b)
{
return a.find(b) != string::npos;
}
It seems you want to erase everything that comes after str.find(a[1]). In that case you can omit the second argument.
#include <iostream>
#include <string>
int main(int argc, char *argv[]) {
std::string str = "Hello, world!";
std::string needle = "o,";
str.erase(str.find(needle));
std::cout << str << "\n";
}
In this example I used needle instead of a[1], but the principle is the same.