What I am working on:
Hello. I currently have a char** variable, which is a pointer to an array of strings. I have a loop that occurs, and in this loop the char** needs to be backed up to a vector of structs. So the struct has a variable type of char** inside of it.
Unfortunately, for this piece I have to use the char** type. I am unable to use the char* vName[] type.
What my problem is:
The problem I am currently facing is that when I add a new struct, the char** points to the newest data available in ALL of the structs, not the most recent one.
What I have tried:
I have tried using strcpy, memcpy, and using the plain old values, but they don't seem to work. I have tried using newItem.storedVars[i] = newVars but that doesn't seem to work either.
How can I get or copy the data in the new char** array and store it into the struct without it being modified again by the loop?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct StringHolder{
char** storedVars; //stored char** variable
};
int main(int argc, char *argv[]){
char** newVars; //stores current char** values
int counter = 100; //counter
vector<StringHolder> vectorOfStructs;
while(counter!=0){ //while counter is going downward
StringHolder newItem; //create a new string
char** storedVarsToAdd; //stored variables that I will be adding
newVars = externalVarsFetcher(); //get the new char** variable from the external function
storedVarsToAdd = newVars; //this statement doesn't work
//neither does this statement
for(int i = 0; i < 10; i++){
storedVarsToAdd[i] = newVars[i];
}
newItem.storedVars = storedVarsToAdd; //take the new item I created, update it's char** value with a new one
vectorOfStructs.push_back(newItem); //push the struct onto the vector
counter--; //continue through the array
}
}
Your problem is that you are just juggling pointers, you are not copying the strings. You should be using std::string, but this sounds like homework so you have probably been told not to do that. If that's not the case use std::string
If you must use char** etc.:
for(int i = 0; i < 10; i++){
storedVarsToAdd[i] = strdup(newVars[i]);
}
strdup will allocate memory and copy the string for you.
Now you have a potential memory leak but that's a different issue (hint - use std::string).
Here's how to store the command-line arguments, which is the same thing you're trying to do:
std::vector<std::string> args;
for (int i=0; i<argc; i++)
args.push_back(argv[i]);
Related
#include<iostream>
#include<vector>
using namespace std;
int main(int argc,char** argv){
int n;
if(argc>1)
n=argv[0];
int* stuff=new int[n];
vector<int> v(100000);
delete stuff;
return 0;
}
When I try to run this code snippet I got an error invalid conversion from char * to int fpermissive. I can not figure out what does this error indicate. If any one have any idea please help me to find out its meaning.
Thank you in advance.
argv is a pointer to a pointer to a character which in short you can assume as pointer to strings and you assign an element of that directly to n.
n is a character array.
First convert n to an integer by atoi() which you can find in stdlib.h
I guess in C++ it is cstdlib.
You can't assign a char* pointer to anintvariable, unless you type-cast it, which is not what you need in this situation. You need to parse thechar*string using a function that interprets the *content* of the string and returns a translated integer, such as [std::atoi()](https://en.cppreference.com/w/cpp/string/byte/atoi), [std::stoi()`](https://en.cppreference.com/w/cpp/string/basic_string/stol), etc.
Also, you are not initializing n if the user runs your app without entering a command-line parameter. And the first user-entered parameter is stored in argv[1], argv[0] contains the calling app's path/filename instead.
Also, you need to use delete[] instead of delete. Rule of thumb - use new and delete together, and new[] and delete[] together. Or prefer to not use them directly at all (use std::vector, std::make_unique<T[]>(), etc instead).
Try something more like this:
#include <iostream>
#include <vector>
#include <cstdlib>
using namespace std;
int main(int argc,char** argv){
int n = 0; // <-- initialize your variables!
if (argc > 1)
n = atoi(argv[1]); // <-- [1] instead of [0]! and parse the string...
int* stuff = new int[n];
vector<int> v(100000);
delete[] stuff; // <-- use delete[] instead of delete!
return 0;
}
I'm making a new app for my lab and I must take form terminal some arguments, and I want to copy the **args value into a string, and after that I must match the args for execute some foreplay operation.
I try to build this code to copy the **argv value into string var but this is the error:
No source available for "std::string::operator=() at 0x44c1dc"
The code is this:
int main(int argc, char **argv)
{
string args[argc-1];
int j=0;
for(int i=2; i<argc-1;i++)
{
j=0;
while(argv[i][j]!='\0')
{
args[i]=args[i]+argv[i][j];
j++;
}
}
return 0;
}
I would propose this solution:
std::vector<std::string> args;
std::copy(argv + 1, argv + argc, std::back_inserter(args));
References:
std::copy
std::back_inserter
To explain it a little, this copies from argv[1] (I don't care about argv[0] as it's the "command" and usually irrelevant for argument handling) into the vector. We stop copying at argv[argc] which is one beyond the end of the actual arguments (which is how "end" iterators work).
std::back_inserter creates a special iterator that is used to insert ad the end of containers.
Fastest and shortest solution with range constructor:
std::vector<std::string> args(argv + 1,argv + argc);
Make things as clear as you can. (Will help those 3am debugging sessions in your laboratory).
int main(int argc, char **argv)
{
std::vector<std::string> args(argc);
for (int i = 0; i < argc; ++i){
args[i] = argv[i];
}
// rest of code here.
}
Yes I know I waste args[0], but do you really care about that? The indexing is so much clearer if you do it this way, args has the same indexing conventions as argv (which all us old cats are used to), and you don't get a whole lot of edge cases when you only pass the program name.
There are a few mistakes in your code, which also causes the odd problems. Also you're overcomplicating things quite a bit.
Here's what I'd do, this will require one additional header, <vector>, for the STL container, but it will make things a lot easier (since you shouldn't rely on being able to create arrays with dynamic lengths (also note that your array length might be 0, if there are no arguments given!))
int main(int argc, char **argv) {
std::vector<const std::string>> params; // This is the container that will take all arguments.
// Iterate over all arguments provided
// (skipping the very first, since that's the executable itself)
for (int i = 1; i < argc; i++)
// Add the argument to the vector
// (this will construct a new std::string and add it to the end).
params.push_back(argv[i]);
// You're now able to access the arguments passed:
// params.size() will return the number of arguments.
// params[i] will return the i-th argument, starting at 0.
return 0;
}
int main(int argc, char **argv)
{
string args[argc];
int j=0;
for(int i=2; i<argc;i++)
{
args[i-2].assign(argv[i]);
}
return 0;
}
first, you can't use a dynamic argument in a static expression.
you must use either new to create a string array, or, better yet, use a vector (or any other container you like).
second, there is no point in copying the values one character by another. copy the entire string.
here is a sample code that will work:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef vector<string> svec;
int main(int argc,char **argv)
{
svec strings;
if(argc>1)
{
cout <<"arguments:"<<endl;
for(int i=1;i<argc;i++)
{
strings.push_back(argv[i]);
}
}
for(auto i:strings)
{
cout << i;
}
return 0;
}
D.
I have the following bit of code:
As a global variable:
char *orderFiles[10];
And then my main method:
int main(int argc, char *argv[])
{
orderFiles = argv;
}
However it keeps giving me an error. What am I doing wrong?
It's giving you an error because char *x[10] gives you an array of ten char pointers which is non-modifiable. In other words, you cannot assign to x, nor change it in any way. The equivalent changeable version would be char **orderFiles - you can assign argv to that just fine.
As an aside, you could transfer individual arguments to your array thus:
for (i = 0; i <= argc && i < sizeof(orderFiles)/(sizeof(*orderFiles); i++)
orderFiles[i] = argv[i];
but that seems rather convoluted. It will either fill up orderFiles with the first N arguments or partially fill it, making the next one NULL.
If your intent is simply to stash away the arguments into a global so that you can reference them anywhere, you should do something like:
#include <stdio.h>
char **orderFiles;
int orderCount;
static void someFn (void) {
int i;
printf ("Count = %d\n", orderCount);
for (i = 0; i < orderCount; i++)
printf ("%3d: [%s]\n", i, orderFiles[i]);
// or, without orderCount:
// for (i = 0; orderFiles[i] != NULL; i++)
// printf ("%3d: [%s]\n", i, orderFiles[i]);
// printf ("Count was %d\n", i);
}
int main (int argc, char **argv) {
orderCount = argc;
orderFiles = argv;
someFn();
return 0;
}
That code saves the arguments into globals so they can be accessed in a different function.
You should save both arguments to main if you want to use argc as well although, technically, it's not necessary since argv[argc] is guaranteed to be NULL for hosted environments - you could use that to detect the end of the argument array.
orderFiles is a const char **, you can't modify it (the array pointer itself).
You could try assigning the array members (i.e. orderFiles[0] = argv[0] and so on).
The problem is that there is a difference between arrays initialized without a length, and those initialized with one. Remove the 10 from the global variables declaration, and then it should work
The reason for this is that argv is really just a char**, but orderFiles is an array of 10 char*.
There is an implicit char** for orderFiles yes, but it's constant because you initialized it to a link time allocated block of memory by specifying the size [10]. You should create a non-constant char** or maybe memcpy from argv to your array.
Like they all said two different data types. In other terms think of it this way: argv is an array of c-strings, and your orderFiles is declared as a single c-string.
So how to assign orderFiles depends on what you're trying to do. I typically iterate through argv to get the arguments passed to the application. Note that argv[0] is the application name.
I've been programming badly for quite a while and I only really just realised. I have previously created many functions that return character strings as char arrays (or at least pointers to them).
The other day someone pointed out that when my functions return the char arrays pointed to by my functions have gone out of scope and I'm essentially now pointing to a random bit of memory (A nasty dangling pointer).
I didn't really notice this for a while because the char arrays when outputted to the console didn't appear to be corrupt (probably because there wasn't time for that data to be overwritten). I did however notice this when I was returning a string buffer (char array) generated by reading the serial port which was frequently corrupt.
So, how best should I do it?
My bad code is as follows:
#include <cstdlib>
#include <iostream>
using namespace std;
char* myBadFunction(){
char charArray[] = "Some string\n";
char* charPointer = charArray;
return charPointer;
}
int main(int argc, char** argv) {
cout << myBadFunction();
return 0;
}
I understand that I should perhaps allocate memory in the program before calling the function or create a global variable to put the returned string in, but if my called function is used by many different programs when how should it know the size of the buffer being passed into it in advance and when should this memory be deleted?
The following code also doesn't do what I want it to properly:
#include <cstdlib>
#include <iostream>
using namespace std;
void fillArray(char* charPointer){
char charArray[] = "Some string\n"; // Create string
charPointer = charArray; // Not correct, want to fill predefined array with created string
return;
}
int main(int argc, char** argv) {
char predefinedArray[50] = {0};
fillArray(predefinedArray);
cout << predefinedArray;
return 0;
}
I want to fill the array that the pointer parsed points to but this doesnt' happen in the code above.
Also, when should I use the new[] command to create my array? is it needed? and when should I call delete[] on it.
Many thanks for this, its obviously very fundamental but something I've been doing wrong for a while.
The simplest way would be to return a std::string, and if you needed access to the internal char array use std::string::c_str().
#include <iostream>
#include <string>
using namespace std;
string myGoodFunction(){
char charArray[] = "Some string\n";
return string(charArray);
}
int main(int argc, char** argv) {
cout << myGoodFunction();
return 0;
}
If you need to return something other than a char array, remember that pointers can be used as iterators. This allows you to encapsulate an array in a vector or a similar structure:
vector<int> returnInts() {
int someNums[] = { 1, 2, 3, 4 };
return vector<int>(someNums, someNums + 4);
}
You have two options for returning an array in C++. You can fill in pre-allocated memory (good), or allocate your own within the function and return it (bad). The reason that the first is preferred is because it re-enforces proper disposal of allocated memory.
A basic example would look like this:
void fillArray(char* buffer, int sz) {
char text[] = "hello there!";
if (sizeof(text)>sz) {
// overflow! Buffer is too small!
return;
}
for (int n=0;n<sizeof(text);n++) {
buffer[n] = text[n];
}
}
int main() {
char* buffer = new char[30]; // allocates a buffer of 30 bytes.
fillArray(buffer,30);
cout << buffer;
delete [] buffer;
}
/* note that it would be easier to use static memory in this example */
It isn't hard when you think about the problem.
Declare the array as "static" varible and return with its address.
This code works, but causes a warning :
#include <cstdlib>
#include <iostream>
using namespace std;
char* myBadFunction(){
static char charArray[] = "Some string\n"; // insert "static"
// char* charPointer = charArray;
return charArray; // charArray is a pointer to the static array
} // after returning static varibles stay safe
int main(int argc, char** argv) {
cout << myBadFunction();
return 0;
}
"Some string\n" is a string literal and will therefore exist for the lifetime of the program, so the following would be valid:
#include <cstdlib>
#include <iostream>
using namespace std;
char* myGoodFunction(){
char* charPointer = "Some string\n";
return charPointer;
}
int main(int argc, char** argv) {
cout << myGoodFunction();
return 0;
}
Of course this is only useful if the function always returns the same string. If the returned string can vary (generally the case) then you can declare the char array in your function as static and return it's address (as has already been suggested).
Is there a way to define a global variable by user input?
Lets say I use
#include...
#define N 12
double array[N][N];
void main();...
But I would like the user to be able to choose what N is.
Do I have to have N as a local variable or is there a way around this(without macros)?
I've a pretty small program but with a lot of different variables that need the N value.
Alternatively,
is there a way I could send a group of variables into a function without having to explicitly write them out every time.
for example
myfunction(var1,var2,var3...)
and instead write something like
myfunction(Allvariables)
Thanks a lot for Your answers!
This is a great forum.
int* data;
int main()
{
int n;
// get n from the user.
data = new int[n];
// use data.
.
.
delete[] data;
}
or just forget pointers for ever and use vector!
std::vector<int> data;
data.push_back(55);
// just push_back data!
=======================================================================
EDIT ::
If you want to use Edouard A. way :)
#include <iostream>
#include <sstream>
#include <vector>
int main(int argc, char* argv[])
{
std::vector<double>::size_type dataSize = 0;
std::stringstream convertor(argv[1]);
{
if(argc > 1)
{
convertor >> dataSize;
if(convertor.fail() == true)
{
// do whatever you want here in case
// the user didn't input a number.
}
}
}
std::vector<double> data(dataSize);
// use the vector here.
return 0;
}
I prefere to use lexical_cast in this case, but I am not sure if you have Boost.
#include <iostream>
#include <vector>
#include <boost/lexical_cast.hpp>
int main(int argc, char* argv[])
{
typedef std::vector<double>::size_type vectorSize;
if(argc < 2)
{
// err! The user didn't input anything.
}
vectorSize dataSize = boost::lexical_cast<vectorSize>(argv[1]);
std::vector<double> data(dataSize);
// use the vector here.
return 0;
}
1/ Yes but you need dynamic memory allocation. The program parameters are passed as argc and argv to the main function
int main(int argc, char **argv)
argc is the number of parameters
argv is the array of null terminated strings representing these arguments
argv[0] is the program itself.
2/You can either use variadic function va_start & the like, or functions overriding, or group your data in a structure and pass that to the function
No, that can't be done this way. You need to use dynamic (runtime) memory allocation (new[]). To perform static (compile-time) memory allocation the compiler needs to know the memory block size at compile time.
I'm not really sure what you're trying to do with myFunction but it sounds like you want to look at either creating a struct or pass a std::vector
Make a class (or struct) AllVariables and pass that in.
You don't say whether you want N defined at run time or compile time. If you want it defined at compile time, you can define N as a compiler command line arguement.