Trying to create an output file with freopen, using non-constant string - c++

I'm trying to create a file whose name is a string constant, but a string consisting of a constant string "List" an integer + + an extension. Here's my code:
#include <iostream>
#include <vector>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
using namespace std;
int main (){
int cont=0;
std::string result;
std::string name = "Lista";
std::string ext = ".txt";
char numstr[21]; // enough to hold all numbers up to 64-bits
sprintf(numstr, "%d", cont);
result = name + numstr+ext;
freopen (result, "w", stdout);
cout<<result<<endl;
return 0;
}
When I try to build tells me the following error:
error: cannot convert std::string' toconst char*' for argument 1'
toFILE* freopen(const char*, const char*, FILE*)'|
How I can solve this?

As the compiler error states there is no implicit conversion from std::string to char const* (ie. a c-style-string in this context).
Though std::string has a member-function named c_str which will generate a null-terminated string and return a pointer to it that is very usable when dealing with legacy C functions.
Examples and notes
freopen (result.c_str (), "w", stdout);
char const * p = result.c_str ();
Please note that the c-style-string pointed towards by std::string::c_str will be invalidated if you make any modifications to the hosting object (in this case result), therefore it is normally not wise to store the value returned in a non-temporary variable.
You can read more about the function if you follow the link below:
cppreference.com - std::basic_string::c_str

i have a small app that does this exactly. there are several ways to do this.. the simplest of which is
const char * newvar = stringname.c_str();

If you're going to use sprintf, it's probably easiest to skip using std::string at all:
char name[32];
sprintf(name, "lista%d.txt", cont);
freopen(name, "w", stdout);
If you're going to use std::string (probably preferable for most C++ anyway), you probably want to use std::stringstream to create the name:
std::ostringstream name;
name << "lista" << cont << ".txt";
freopen(name.str().c_str(), "w", stdout);
However, I'd tend to avoid freopen in general, and avoid using C-style streams (such as stout) in C++. It's generally better to write to an ostream. Answers to a previous question show how to connect cout to a different output file, if you truly need to.

Related

How can I copy multiple char* strings into one using strcpy_s()?

Using the strcpy_s() function I want to collate the first three strings into the final one to print my full name. This is what I have and it doesn't work as I'm using char* strings and not std::strings.
#include <iostream>
using namespace std;
int main()
{
char str_first[] = "Nerf_";
char str_middle[] = " Herder";
char str_last[] = "42";
char str_fullName[35];
strcpy_s(str_fullName, (str_first + str_middle + str_last).c_str());
cout << str_fullName;
}
Any suggestions?
This should be close to what you're looking for, strictly using strcpy_s to concatenate strings together:
#include <string.h>
#include <iostream>
using namespace std;
int main()
{
char str_first[] = "Nerf_";
char str_middle[] = " Herder";
char str_last[] = "42";
char str_fullName[35];
int index = strcpy_s(str_fullName, sizeof str_fullName, str_first);
index += strcpy_s(str_fullName + index, sizeof str_fullName - index, str_middle);
index += strcpy_s(str_fullName + index, sizeof str_fullName - index, str_last);
cout << str_fullName;
}
The index variable serves a couple of purposes: (1) to provide a new index into the output str_fullName string as the string is built, and (2) subtracted from sizeof str_fullName, it "adjusts" the available buffer size as the string is built.
Caveats are that you should add overflow checking via the output from strcpy_s, and (as noted by others) there are better patterns to follow for doing this, but probably as an academic exercise there's something good to be learned here.
You need to use both strcat and strcpy
See code comments for more info.
// disable SDL warnings in Visual studio
#define _CRT_SECURE_NO_WARNINGS
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
// TODO: insert checking code,
// to make sure destination can hold all characters + one termination.
char str_first[] = "Nerf_";
char str_middle[] = " Herder";
char str_last[] = "42";
char str_fullName[35];
// copy first string because we need null terminated destination
strcpy(str_fullName, str_first);
// append the rest, string is auto null terminated.
strcat(str_fullName, str_middle);
strcat(str_fullName, str_last);
cout << str_fullName;
}
If I am not mistaken the function strcpy_s expects three arguments. So either supply one more argument to the function call or use instead the function strcpy.
And there is no need to use the standard class std::string to perform the task.
The code can look the following way
strcpy( str_fullName, str_first );
strcat( str_fullName, str_middle );
strcat( str_fullName, str_last );
Or you could use strcpy_s and strcat_s provided that you will specify the correct number of arguments.
Pay attention to that you need to include the header
#include <cstring>

Program not coutting

I am using th following code but it only asks me for a input and closes without couting my input
#include <iostream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main(){
int balance=0;
int withdraw=0;
char* str;
cin.getline(str,10);
cout<<str;
withdraw=atoi(strtok(str," "));
balance=atoi(strtok(NULL," "));
cout<<withdraw<<" "<<balance;
return 0;
}
char* str;
This only gives you a pointer. That pointer doesn't point anywhere, especially not at some chars that you can write to. When you call cin.getline(str,10), it tries to write to where this pointer is pointing to. That gives you undefined behaviour. An easy fix for this is to make str an array of 10 chars:
char str[10];
However, I recommend that you start using std::string instead and figure out how to do strtok-like operations with a std::string. Hint: look at std::istringstream.
You need to allocate memory for str.
char *str = new char[10];
otherwise using uninitialized pointer will invoke undefined behavior. And call delete to free the allocated memory once you done with str.
delete[] str;
Instead of using char *, it is better to use std::string.

can't get argv to pass to string

I'm new to C++ programming (haven't done it in 10+ since college.) and I'm trying to write a very basic program to grab a file name that has been passed as an argument. I'm just not getting how to get the file name. I'm using VS2012 Exp for Desktop.
Below is my code.
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <xstring>
#include <string>
//using namespace openutils;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
wcout << "customconsole app has "<< argc <<" arguments passed. second one is: " << argv[1];
ofstream me_attach_file;
wstring newfilename = argv[1] && ".newext";
me_attach_file.open (".mailexpress");
me_attach_file << "Writing this to a file.\n";
me_attach_file.close();
return 0;
}
Replace this
wstring newfilename = argv[1] && ".newext";
with
wstring newfilename = argv[1];
newfilename += L".newext";
Some languages use & for string concatenation. C++ does not. In fact, there is NO operator that concatenates string literals and character pointers: + as string concatenation is defined by string objects and works only with them.
In addition, string literals have to be prefixed with L to use wide characters and be compatible with wstring.
&& doesn't add two strings together. The + operator does.
Also, C++ decides which of the many operator + functions to use by the type of the left-hand argument. You have two different types here, a _TCHAR string, a string literal ("this is a string literal") which is type char*, and you want to put it into a wstring.
First, a _TCHAR and char* aren't the same type, so it should be L".newext".
Second, you can't add two char*s, because that is adding two pointers, and pointer arithmatic does something different than what you want. So the first argument needs to be coverted to a wstring before you start adding things together.
Either:
wstring myStr = argv[1];
myStr += L".newext"
Or:
wstring myStr = wstring(argv[1]) + L".newext" + L"Additional stuff"
in the line
me_attach_file.open (".mailexpress");
you should pass the filename to the object.
me_attach_file.open (newfilename);
in your version, ofstream will open a file named ".mailexpress" without prefix (which is hidden on unix systems).

Creating a string with char[]

#include <iostream>
using namespace std;
int main()
{
char strin[206];
strin = "sds";
cout<<strin;
}
Why do I get this error?
error: incompatible types in assignment of 'const char [4]' to 'char [206]' //on line strin = "sds"
I am following this beginner tutorial
The error comes from the fact that you're trying to assign one array into another. The assignment operator can't do that; you'd have to copy the array using strcpy() or std::copy().
However, since you want to work in C++, you should really be using std::string instead of char[] to store strings.
You can not assign an array to another directly. It should be copied element to element.
Use std::strcpy from <cstring> header
char strin[206];
std::strcpy(strin, "sds");
Use std::string from <string> header
std::string strin;
strin = "sds";
Since you're using C++, choose second one.
Your code;
strin = "sds";
should be:
strcpy(strin, "sds");
C/C++ doesn't have string opertions built-in. You need to use either function:
strcpy(strin, "sds"); // will work in C and C++
// strncpy(strin, "sds", 205); // safer if you want to copy user-given string
or std::string:
std::string strin(206, 0);
strin = "sds"; // only C++
strin is a array which is a const pointer to chars, not a pointer to chars.
You tried to change the const pointer and this is forbidden
you need to copy the string. e.g. this way
strcpy (string, "sds");
(Aware buffer overflows in general cases!)

Function that will act like an Strlen C++

I want to make a function that will do the same as Strlen does, andI get the error: "string subscript out of range". I tried fixing it but has no idea.
heres the code:
#include "stdafx.h"
#include "stdafx.h"
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int strlen1( string str)
{
int count=0;
int i=0;
while (str[i]!='\0')
{
count++;
i++;
}
return count;
}
int _tmain(int argc, _TCHAR* argv[])
{
string input;
cin >> input;
cout << strlen1(input) << endl;
return 0;
}
thanks!
In short, for a non-const std::stringaccessing an element beyond the string length has Undefined Behavior (more precisely, when using the non-const operator[] for that).
C++98 ยง21.3.4/1, about std::string::operator[]:
If pos < size, returns data()[pos]. Otherwise, if pos == size(), the const version returns charT(). Otherwise the behavior is undefined.
And your string is non-const.
You can make it const, which will then invoke a special provision in the standard that guarantees zero result for element n, but that does not address the problem that your function is completely redundant for std::string.
Perhaps you mean to have argument type char const*.
That would make more sense, and then also the function would work.
Cheers & hth.,
You seem to be under the misconception that std::string is the same as a C-style string (char const*). This is simply not true. There is no null terminator.
Here's your strlen function the only way it will work:
int strlen1(string str) { return static_cast<int>(str.size()); }
std::string has a nice size() method for this.
strlen is based on zero terminated strings (char*, or char arrays), C++ string are based on length + data, you can't access to data after the end of string (where a terminal zero would be). Beside that, getting the length is a standard property of C++ strings (size()), hence the standard way of writing strlen is just to call size.