i am trying to put the words that there are in a txt file* into an array of strings.
But there is an error with the strcpy(). it sais: 'strcpy' : cannot convert parameter 1 from 'std::string' to 'char *' . Why is that? Isn't it possible to create an array of strings like this in c++?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void ArrayFillingStopWords(string *p);
int main()
{
string p[319];//lekseis sto stopwords
ArrayFillingStopWords(p);
for(int i=0; i<319; i++)
{
cout << p[i];
}
return 0;
}
void ArrayFillingStopWords(string *p)
{
char c;
int i=0;
string word="";
ifstream stopwords;
stopwords.open("stopWords.txt");
if( stopwords.is_open() )
{
while( stopwords.good() )
{
c = (char)stopwords.get();
if(isalpha(c))
{
word = word + c;
}
else
{
strcpy (p[i], word);//<---
word = "";
i++;
}
}
}
else
{
cout << "error opening file";
}
stopwords.close();
}
I suggest strcpy (p[i], word); be changed to p[i] = word;. This is the C++ way of doing things and takes advantage of the std::string assignment operator.
You don't need strcpy here. A simple assignment will do it: p[i] = word;. strcpy is for C-style strings, which are null-terminated arrays of characters:
const char text[] = "abcd";
char target[5];
strcpy(target, text);
Using std::string means you don't have to worry about getting the size of the array right, or about calling functions like strcpy.
Related
I want to write a function that receive an int argument then converter to a char pointer (c-string), but my code output is not right.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
char *stoc(int n){
stringstream stream;
stream <<"Log"<<n<<".txt";
string name;
stream >>name;
int len = name.length();
char ch[len+1];
for(int i=0; i<len; i++){
ch[i]=name[i];
}
ch[len+1] = '\0';
return ch;
}
int main() {
char *name = stoc(3);
cout << name << endl;
return 0;
}
Summarising the comments:
You normally do not use C-style-strings in C++, just stick to std::strings. Therefor you should rather return name instead of your converted ch, especially since you have already created a std::string. Having access to at least C++11 you can then easily convert your rather long function into a one-liner
C++11
std::string stoc(int n) {
return "Log" + std::to_string(n) + ".txt";
}
prior C++11
std::string stoc(int n) {
std::ostringstream oss;
oss << "Log" + n + ".txt";
return oss.str(); // by accessing a stringstreams content directly there is no need to use an extra variable
}
If you do need to use a C-style-string later on somewhere, e.g. as a parameter for a C-library function, you can use c_str to convert any std::string into it's C-style equivalent:
int main() {
std::string name = stoc(3);
std::cout << name << std::endl;
}
You should do this instead of returning a pointer to a local variable (which yields in undefined behaviour):
...
char *ch = new char[len+1];
for(int i=0; i<len; i++){
ch[i]=name[i];
}
ch[len] = '\0';
...
int main() {
char *name = stoc(3);
cout << name << endl;
delete [] name; // delete what has been allocated in stoc
return 0;
}
Also note the ch[len] = '\0' instead of ch[len + 1] = '\0'.
But in C++ you should rather use std::string and not deal with char arrays, new and delete at all.
I wrote a simple C++ program to reverse a string. I store a string in character array. To reverse a string I am using same character array and temp variable to swap the characters of an array.
#include<iostream>
#include<string>
using namespace std;
void reverseChar(char* str);
char str[50],rstr[50];
int i,n;
int main()
{
cout<<"Please Enter the String: ";
cin.getline(str,50);
reverseChar(str);
cout<<str;
return 0;
}
void reverseChar(char* str)
{
for(i=0;i<sizeof(str)/2;i++)
{
char temp=str[i];
str[i]=str[sizeof(str)-i-1];
str[sizeof(str)-i-1]=temp;
}
}
Now this method is not working and, I am getting the NULL String as result after the program execution.
So I want to know why I can't equate character array, why wouldn't this program work. And what is the solution or trick that I can use to make the same program work?
sizeof(str) does not do what you expect.
Given a char *str, sizeof(str) will not give you the length of that string. Instead, it will give you the number of bytes that a pointer occupies. You are probably looking for strlen() instead.
If we fixed that, we would have:
for(i=0;i<strlen(str)/2;i++)
{
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
}
This is C++, use std::swap()
In C++, if you want to swap the contents of two variables, use std::swap instead of the temporary variable.
So instead of:
char temp=str[i];
str[i]=str[strlen(str)-i-1];
str[strlen(str)-i-1]=temp;
You would just write:
swap(str[i], str[sizeof(str) - i - 1]);
Note how much clearer that is.
You're using C++, just use std::reverse()
std::reverse(str, str + strlen(str));
Global variables
It's extremely poor practice to make variables global if they don't need to be. In particular, I'm referring to i about this.
Executive Summary
If I was to write this function, it would look like one of the two following implementations:
void reverseChar(char* str) {
const size_t len = strlen(str);
for(size_t i=0; i<len/2; i++)
swap(str[i], str[len-i-1]);
}
void reverseChar(char* str) {
std::reverse(str, str + strlen(str));
}
When tested, both of these produce dlrow olleh on an input of hello world.
The problem is that within your function, str is not an array but a pointer. So sizeof will get you the size of the pointer, not the length of the array it points to. Also, even if it gave you the size of the array, that is not the length of the string. For this, better use strlen.
To avoid multiple calls to strlen, give the function another parameter, which tells the length:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
and call it with
reverseChar(str, strlen(str))
Another improvement, as mentioned in the comments, is to use std::swap in the loop body:
void reverseChar(char* str, int len)
{
for(i=0; i<len/2; i++)
{
std::swap(str[i], str[len-i-1]);
}
}
Also, there is std::reverse which does almost exactly that.
//reverse a string
#include<iostream>
using namespace std;
int strlen(char * str) {
int len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
void reverse(char* str, int len) {
for(int i=0; i<len/2; i++) {
char temp=str[i];
str[i]=str[len-i-1];
str[len-i-1]=temp;
}
}
int main() {
char str[100];
cin.getline(str,100);
reverse(str, strlen(str));
cout<<str<<endl;
getchar();
return 0;
}
If I were you, I would just write it like so:
int main()
{
string str;
cout << "Enter a string: " << endl;
getline(cin, str);
for (int x = str.length() - 1; x > -1; x--)
{
cout << str[x];
}
return 0;
}
This is a very simple way to do it and works great.
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char str[80];
cout << "Enter a string bro: \n";
gets_s(str);
for (int i = strlen(str) - 1; i > -1; i--)
{
cout << str[i];
}
}
I have to admit, i have no idea how to use pointers, but I tried non the less. the problem with my program is that it shows the string in reverse, except for what was the first letter being missing and the entire string is moved one space forward with the first element being blank.
for example it show " olle" when typing "hello".
#include <iostream>
#include <string>
using namespace std;
string reverse(string word);
int main()
{
char Cstring[50];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(string word)
{
char *front;
char *rear;
for (int i=0;i< (word.length()/2);i++)
{
front[0]=word[i];
rear[0]=word[word.length()-i];
word[i]=*rear;
word[word.length()-i]=*front;
}
return word;
}
The new code works perfectly. changed the strings to cstrings. the question technicaly asked for cstrings but i find strings easier so i work with strings then make the necesary changes to make it c string. figured out ho to initialize the rear and front as well.
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
char *front;
char *rear;
then later
front[0]=word[i];
rear[0]=word[strlen(word)-1-i];
Not good. Dereferencing uninitialized pointers invokes undefined behavior.
Apart from that, your code is overly complicated, it calls strlen() during each iteration (and even multiple times), which is superfluous, and the swap logic is also unnecessarily complex. Try using two pointers instead and your code will be much cleaner:
void rev_string(char *str)
{
char *p = str, *s = str + strlen(str) - 1;
while (p < s) {
char tmp = *p;
*p++ = *s;
*s-- = tmp;
}
}
The thing is, however, that in C++ there's rarely a good reason for using raw pointers. How about using std::reverse() instead?
string s = "foobar";
std::reverse(s.begin(), s.end());
inline void swap(char* a, char* b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
inline void reverse_string(char* pstart, char* pend)
{
while(pstart < pend)
{
swap(pstart++, pend--);
}
}
int main()
{
char pstring[] = "asfasd Lucy Beverman";
auto pstart = std::begin(pstring);
auto pend = std::end(pstring);
pend -= 2; // end points 1 past the null character, so have to go back 2
std::cout << pstring << std::endl;
reverse_string(pstart, pend);
std::cout << pstring << std::endl;
return 0;
}
you can also do it like this:
#include <iostream>
#include <cstring>
using namespace std;
string reverse(char word[20]);
int main()
{
char Cstring[20];
cout<<"enter a word: ";
cin>>Cstring;
string results = reverse(Cstring);
cout <<results;
}
string reverse(char word[20])
{
char a='a';
char b='b';
char *front=&a;
char *rear=&b;
for (int i=0;i< (strlen(word)/2);i++)
{
*front=word[i];
*rear=word[strlen(word)-1-i];
word[i]=*rear;
word[strlen(word)-1-i]=*front;
}
return word;
}
it successfully works on my system ,i.e. on emacs+gcc on windows 7
Taken from C How To Program Deitel & Deitel 8th edition:
void reverse(const char * const sPtr)
{
if (sPtr[0] == '\0')
return;
else
reverse(&sPtr[1]);
putchar(sPtr[0]);
}
So I tried to do this:
#include <iostream>//For cout/cin
#include <fstream> //For ifstream/ofstream
using namespace std;
int main()
{
string types[] = {"Creativity", "Action", "Service"};
for(int i = 0; i < sizeof(types)/sizeof(string); i++) {
string type = types[i];
string filename = type + ".html";
ofstream newFile(filename);
//newFile << toHTML(getActivities(type));
newFile.close();
}
return 0;
}
and I'm being hit with errors. I'm new to C++, so I don't know what to try, or if this is even possible (SURELY it is...).
I tried the following, but it was really just a stab in the dark and didn't help:
#include <iostream>//For cout/cin
#include <fstream> //For ifstream/ofstream
using namespace std;
int main()
{
string types[] = {"Creativity", "Action", "Service"};
for(int i = 0; i < sizeof(types)/sizeof(string); i++) {
string type = types[i];
//Attempting to add const..
const string filename = type + ".html";
ofstream newFile(filename);
//newFile << toHTML(getActivities(type));
newFile.close();
}
return 0;
}
I mean, its all happy if I do `ofstream newFile("somefile.html");
The original IOstream library didn't have a constructor taking a std::string. The only type supported was char const*. You can get a char const* from a std::string using c_str():
std::string name("whatever");
std::ofstream out(name.c_str());
The type of a string literal isn't of type std::string but it is of type char const[n] where n is the number of characters in the string, including the terminating null character.
In C++ 2011 the File stream classes are improved to also take std::string where a string is expected.
void reverse (char s[]){
int len = strlen(s);
int j = len - 1;
for (int i = 0; i < j; i++,j--){
cout << s[i];
char ch = s[i];
s[i] = s[j]; //error line - giving exception, cannot write to the memory
s[j] = ch;
}
}
I am using Visual Studion 2008 and i can't understand whats the problem here .. :s .. I am out of C++ practice :$ .
The problem is that it uses C-style strings instead of C++ style strings. In particular, you are apparently trying to write to a constant string literal:
char const* str = "I cannot be written to";
C++ allows to omit the const here for backwards compatibility but the literal is still constant.
Finally, C++ already has a reverse function:
#include <algorithm>
#include <iostream>
#include <string>
int main() {
std::string str = "Hello world";
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
}
I'd guess the problem is with how you're calling it, probably with a string literal, something like:
reverse("This is a string");
or:
char *string = "This is a string";
reverse(string);
or some other minor variation. In any case, you're trying to write to a string literal, which gives undefined behavior.
Since you're apparently using C++, I'd consider using an std::string instead:
void reverse(std::string &s) {
int j=s.length()-1;
for (int i=0; i<j; i++, j--) {
// ..
}
}
Are you calling this on a const char* or a string literal?
Are you trying to reverse
reverse("foo");
or
char *s = "foo";
reverse(s);
You'll need to create a new string from the non-writeable one and reverse that instead. You can use strdup.
char *s = strdup("foo");
reverse(s);
free(s, strlen(s));
Also note that your question is tagged c++, so you should probably be using std::string.