searching length of sting in arg[] - c++

I'm trying to get string length from char argv array but I don't know how to check this.
I'm writing 3 words to console for example: red blue yellow.
Then I want to write out "yellow" but I don't know how to do that.
I tried to save the words in a file but I don't have backspaces in the file this looks that:
redblueyellow
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main(int argc,char* argv[]) {
string temp;
fstream save;
string tab[argc];
for(int i=1; i<argc; i++) {
if(argv[i]==' ') {
tab[argv]=tab[i];
}
}
return 0;
}

The line
string tab[argc];
is not valid ISO C++, because the length of the array must be a compile-time constant. Some compilers may support variable-length arrays as an extension, though.
However, it is possible to convert the C-style argv strings to a std::vector of std::string. See this question for further information:
Convert command line argument to string
In your code, the line
if(argv[i]==' ') {
does not make sense, as you are comparing a pointer to a string with a character literal.
If you call your program like this
myprogramname red blue yellow
then the following will apply:
argc will have the value 4
argv[0] will point to a string containing myprogramname
argv[1] will point to a string containing red
argv[2] will point to a string containing blue
argv[3] will point to a string containing yellow
argv[4] will have the value NULL
Therefore, if you want to print yellow, you can simply write
std::cout << argv[3] << '\n';
If you want to print the length of the string yellow, you can simply write
std::cout << std::strlen( argv[3] ) << '\n';
Note that you must #include <cstring> in order to use std::strlen.
Alternatively, instead of using std::strlen, you can first convert argv[3] to a std::string, before obtaining its length:
std::string str{ argv[3] };
std::cout << str.length() << '\n';
If you want to write to a file, such as to the std::fstream with the name save in your program, then you can replace std::cout with save in the code above. However, you will have to open the file first, before using it. Also, you may want to consider using std::ofstream instead of std::fstream, because you seem to only want to use the file for writing, not reading.

Related

c++ cstring, Is there any way to get single char from cstring?

char cstri[] = "hello world";
From here, is there any way to get a single char, such as the first e, position at 1, from this cstring?
I tried a few times, and every time it returns the entire string starting from the passed index. So, if I want 'e', position at 1, it returns ello world instead of just e.
I also tried to copy a single char from the string using strncpy() and memcpy(), but it copies the string from index 0 to null, or just the specified amount.
strncpy(b, cstri , 1);
I know a cstring is read-only, but is there no way to get a single char from a cstring?
I want to use printf(), so I can't use char b = cstri[1]
Your question already hints on "C++" and given the additional fact that there is no difference in the memory representation of a C++ std::string and a normal c-string, the answer is simple: just learn how std::string works. Btw. std::string::c_str() then return your nice c-string.
#include <string>
#include <iostream>
int main() {
std::string hw = "hello world";
std::cout << hw << std::endl; // output: "hello world"
std::cout << hw.c_str() << std::endl; // output: "hello world"
std::cout << hw[1] << std::endl; // output: 'e'
return 0;
}
But there are a ton of more features of std::string and also look at what #include <iomanip> can do.

C-String implementation in C++ outputs incorrectly

I was recently working on a problem teaching new users of C++, which I myself am, how to use cstrings and the different implementations of them compared to the imported string object in C++. As I was working on the problem, I came across an error where, despite initializing the size of the cstring to an appropriate length for the operations that were being done, the cstring was being outputted strangely.
When I would go to print out the cstring using cout, it would print some of the cstring correctly, but oftentimes the first several characters were random characters that had nothing to do with the operations being done to the cstring. However, I found a way to definitively prevent those characters from being printed; however, I am curious as to why this works as well as what the issue is here.
I found that adding cout << ""; on its own line prior to printing the cstring resolved the issue of the random characters being outputted when printing the cstring. However, this seems like only a temporary fix and I am looking to find a more educated approach to solving this issue.
Below I have included the code that was causing the errors.
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
int main() {
vector<string> words = {"Hello,", "and", "welcome", "to", "the", "world", "of", "C++!"};
// Calculate the total number of characters in the words vector
// (including an additional character for space)
int length = 0;
for(int i = 0; i < words.size(); i++) {
length += words.at(i).length() + 1;
}
cout << ""; // Removing this line of code will cause the output to do strange things
// Initialize the cstring to be of size length
char cstring[length];
// Build the cstring using cstring library functions
for(int i = 0; i < words.size(); i++) {
strcat(cstring, (words.at(i) + " ").c_str());
}
// Null-terminate the cstring
cstring[length-1] = '\0';
// Output the cstring
cout << cstring << " " << strlen(cstring) << endl;
return 0;
}
If the line of code containing cout << ""; is removed, the output looks something like this, with a random amount and random set of characters at the beginning of the output each time:
`k+��Hello, and welcome to the world o 39
However, by including the line, I am able to achieve the desired output:
Hello, and welcome to the world of C++! 39
For starters variable length arrays is not a standard C++ feature
// Initialize the cstring to be of size length
char cstring[length];
Secondly you defined an uninitialized array. So using strcat invokes undefined behavior
strcat(cstring, (words.at(i) + " ").c_str());
This statement
// Null-terminate the cstring
cstring[length-1] = '\0';
is redundant because the function strcat appends also the terminating zero provided that the character array you declared has a space to accommodate the zero character (and you forgot to reserve a space for the terminating zero in the array).
If the compiler supports variable length arrays then the program can look the following way
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
int main()
{
std::vector<std::string> words =
{
"Hello,", "and", "welcome", "to", "the", "world", "of", "C++!"
};
// Calculate the total number of characters in the words vector
// (including an additional character for space)
size_t length = words.size();
for ( const auto &s : words ) length += s.length();
// Initialize the cstring to be of size length
char cstring[length + 1];
cstring[0] = '\0';
// Build the cstring using cstring library functions
for ( const auto &s : words )
{
std::strcat( cstring, ( s + ' ' ).c_str() );
}
// Output the cstring
std:: cout << cstring << ' ' << length << std::endl;
return 0;
}
The program output is
Hello, and welcome to the world of C++! 40

Read text file into vector (double, double, string)? C++

I have a text format that uses latitude, longitude and name of location
, for example:
41.3333 34.3232 Old Building
I have to read this text file (from the command line), split each line by white space, use stod to convert the lat and long back into a double, then read the whole file into a vector or a list.
This is what I currently I am stuck on:
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
class Distance{
public:
double x;
double y;
string location;
};
int main(int argc, char *argv[]){
// If the user didn't provide a filename command line argument,
// print an error and exit.
if (argc <= 1){
cout << "Usage: " << argv[0] << " <Filename>" << endl;
exit(1);
}
char *pFilename = argv[1];
string buf; // Have a buffer string
stringstream ss(argv[1]); // Insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf)
tokens.push_back(buf);
}
Question:
Could I have some insight on how to proceed with the implementation?
Answer: from here I need to look at each line in the file and split them by whitespace then store the file in a vector by what they are. So the first number of the text file would be latitude, second longitude, and third (string) is location.
These are some general points whenever you end up using C++ :-
Avoid pointers if you can. Prefer references or composite classes like string in place of char *.
The C++ reference online can help you find out the correct usage very easily.
GDB can help you in most of the cases for such problems as in your question.
As suggested in the comments , you have to read the file in the string stream first and then only you can parse it. I have not compiled the code below but I hope it gives you a good idea about how to do this.In this case, the file is standard input. You can read from that in the following manner :-
char buffer[1000]; // assumine each line of input will not be more than this
while(cin.getline(buffer , 1000)) // constant 1000 can be moved to a MACRO
{
// cin does not eat up the newline character. So we have to do something like this to make it work
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
//discard characters until newline is found
stringstream ss(buffer); // Insert the string into a stream
vector<string> tokens; // Create vector to hold our words
string buf ;
Distance distance ;
ss>>buf;
distance.x = stod(buf);
tokens.push_back(buf);
ss>>buf;
distance.x = stod(buf);
tokens.push_back(buf);
ss>>buf;
distance.x = buf;
tokens.push_back(buf);
}

Program stop working by strcat() with pointer

I have a problem, do not to compile this code but, to execute this program. When I run it in the terminal it prints the first 2 cout then the program stops working and the screen on the windows that tells you, i think the problem is to strcat.
I'm using DEVC++ and I have windows 7 pro.
#include <iostream>
#include <string>
#include <cstdlib>
#include <string.h>
using namespace std;
int main() {
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
cout << "*c: " << *c << endl;
cout << "*cambia: " << *cambia << endl;
strcat( *cambia, *c );
cout << "*cambia: " << *cambia << endl;
}
You don't use strcat() in C++ if you don't absolutely have to (e.g. when maintaining legacy code and touching as little stuff as possible).
Use std::string and its member functions like find or substr for simple tasks, string streams or Boost libraries for more complex string splitting.
At any rate, stay away from strcat().
The method strcat() adds the string from the second argument to the buffer of which you submit to the first argument.
First, the buffer has to be writable. In your example, you are passing a string literal as buffer. Naturally, string literals are read-only. But even then, the string literal has no spare space where the new string could be added.
Instead of fixing your code, let me show you some proper examples how to concat strings in C++ and in C.
This example is showing you how to concat two C++ strings:
#include <iostream>
#include <string>
int main(int argc, const char * argv[])
{
// Create a new C++ string with an initial text.
std::string result = "First string part ";
std::cout << "Result: " << result << std::endl;
// Add some text
std::string textToAppend = "and the second part";
result.append(textToAppend);
std::cout << "Result: " << result << std::endl;
return 0;
}
The following example is showing you how to concat two strings in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[])
{
// The two texts to concat
const char *firstText = "This is the first text ";
const char *secondText = "and this is the second one";
// A buffer which is large enough for the operation.
const int bufferSize = 1024;
char buffer[bufferSize];
// Copy the initial text into the buffer.
strncpy(buffer, firstText, bufferSize);
// Add the secon string
strncat(buffer, secondText, bufferSize-strlen(buffer));
// Output the string
printf("Result: %s\n", buffer);
return 0;
}
I suggest, you should use C++ strings if possible. They automatically manage the memory which prevent many memory related issues with C strings.
This line
char* cambia[] = {"ciao "};
creates a variable named cambia in a dynamically created part of memory, called 'stack'. The variable is an array with no declared size, and elements of that array are pointers to characters.
The size of the array follows from the initializer
{"ciao "}
which implies the array will have only one element, and that element is initialized with a value pointing at the first character of string "ciao ". However, the string "ciao " is placed in some completely different area of memory - it is in static block, initialized by a compiler with values found in the program's code. Compiler does not know how you use these values, in particular it doesn't know you will extend it with strcat, so it will not reserve any additional space after the string.
As a result when you concatenate "mondo" to "ciao ", you overwrite some data in memory, possibly some important data...
I'd suggest you to declare local variables for your string, with explicit size:
char cambia[ 20] = "ciao ";
char c[] = "mondo";
This will make a cambia variable long enough to keep 19-character string (plus implicit terminating zero byte '\0', ASCII NUL) and initialize its first 6 bytes with letters 'c', 'i', 'a', 'o', a space ' ' and NUL. Variable c is implicitly sized to 6 (the initializing string length 5 plus 1 for terminating NUL).
Then you can safely concatenate
strcat( cambia, c);
to obtain 11-character string "ciao mondo" and print it out
cout <<"cambia: "<<cambia<<endl;
The problem here is that you are trying to write to a read-only string storage.
These declarations:
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
declare two arrays, each with a constant string member. The "ciao " and "mondo" are located in read-only memory.
So when you call strcat(*cambia, *c), you are trying to write "mondo" onto the end of "ciao ". Not only does this write to read-only memory, but it also writes outside the memory space given for the string - there is only space for 6 char in the "ciao " string, and you are trying to add another 5 to the end of that.
The solution is to reserve some space for each string. There are various ways to do this. Here's a simple one:
char acambia[20] = "ciao "; // Space for 20 characters.
char* cambia[] = { acambia };
Of coruse, not using the extra level of indirection would make it simpler:
char cambia[20] = "ciao ";
char c[] = "mondo";
strcat(cambia, c);
would achieve the correct result.
First of all you need not headers
#include <string>
#include <cstdlib>
because neither declaration from them is used.
Aslo header
#include <string.h>
should be substituted for
#include <cstring>
In these statements
char* cambia[] = {"ciao "};
char* c[] = {"mondo"};
you defined two arrays each of them having one element of type const char *. The compiler should issue either an error or a warning because these definitions are not correct. It would be correctly to define the arrays the following way
const char* cambia[] = {"ciao "};
const char* c[] = {"mondo"};
These two statements define arrays of const pointers to string literals. It is undefined behaviour if there ia an attempt to change a string literal in a program. Programs are allowed to place string literals in a read-only memory.
You are right saying that the main problem is in statement
strcat( *cambia, *c );
Function strcat appends one character array to the end of another character array. So the second cjaracter array must reserve enough memory that accomodates the appended character array. If you even would define correctly array cambia as
char cambia[] = {"ciao "};
it had no enough memory to store also characters of array c.
So before using strcat you need to reserve enough memory where the concatenated result array would be placed.
You could do this for example the following way
char s[11];
strcpy( s, *cambia );
strcat( s, c );
cout << "s: " << s << endl;
Take into account that instead of character arrays you could use objects of standard class std::string
In this case to append one string to another is made very simply. For example
std::string cambia = "ciao ";
std::string c = "mondo";
cambia += c;
Or
cambia.append( c );

Cutting off the end of a char *

So i have a char *. And i want to cut off some bit at the end. So
char *sentence = "My name is Ted";
How do I cut off the Ted. I could make it a string and then use substring (coming from Java thats my go to method) but id rather not do that way. But im not sure how to do it with a char *.
EDIT: Further on the problem. The issue is in a function that takes a process and is meant to return the location when that process is started from. Thats fine i can get that. But the parameter char *procLocation is passed by reference so the location will be sent back there.
I can only get the location that includes the name of the process. I want to cut off the name of the process and just return the location. Ive tried making the location a string and doing a substring (string - length of the processName). Thats fine. But
procLocation = location.c_str(); // where location.substr is the location - the process name
gives back an error: error C2440: '=' : cannot convert from 'const char *' to 'char *'
Since that is a string literal, you can't modify it.
If you did:
char sentence[] = "My name is Ted";
You could simply set the character before Ted to \0.
You might be better off using std::string though.
Instead of cutting off your literal, you could use std::string constructor that copies fewer characters than is available in your char*:
const char *data = "Hello, Ted!";
string s(data, data+8);
cout << s << endl;
This prints Hello, T
This approach is less wasteful than making a std::string and taking a substring.
To your original problem, as you're coming from Java, you should (should, in the sense of RFC2119) definitely use std::string:
#include <string>
#include <iostream>
using namespace std;
int main(int argc, const char** argv) {
// copy c-string to std::string
string arg0 = argv[0];
cout << arg0 << endl;
// find last occurrence of path separator
size_t found = arg0.find_last_of("/\\");
// split off filename part of string
cout << arg0.substr(0,found) << endl;
return 0;
}
Further, you should not (should not, in the sense of RFC2119) declare the char array as a char pointer, but as a char array:
char[] s0 = "Hello World!"; // <-- is better
char * s1 = "Hello World!"; // <-- avoid this
See this post for actual reasons why this is better. It also gives the reasons for why not to modify such rvalue strings.
You've tagged the question 'c++' and 'string' but you say you don't want to do this with string and substr ? Not sure why that is. You should prefer these over char* and C style string manipulation functions wherever possible.
To do it the C++ way:
string sentence = "My name is Ted";
cout << "\"" << sentence.substr(0, sentence.rfind(' ') ) << "\"" << endl;
Although you could (modifying your code slightly so that you have a mutable string) do this in C:
char sentence[] = "My name is Ted";
*strrchr(sentence, ' ') = '\0';
printf("\"%s\"\n", sentence);