#include <iostream>
using namespace std;
void mystrcat(char destination[], const char source[]){
int counter = 0;
while(source[counter] != '/0'){
destination += source[counter];
counter++;
}
destination += '/0';
}
int main(){
}
For my code, when I try to concatenate with the function mystrcat, my school's test bed says that there was a segmentation error. The purpose of my function is to concatenate while removing the NULL from the end of destination and adding it to the end of source. Is there a segmentation error because I am not removing NULL? If so, how do I access the last element of the array? The number of elements is unknown so I don't know if I can use pop_back. Thank you.
Edit:
#include <iostream>
using namespace std;
void mystrcat(char destination[], const char source[]){
int counter = 0;
int counter2 = 0;
while(destination[counter2] != '/0'){
counter2++;
}
while(source[counter] != '/0'){
destination[counter2 - 1] = source[counter];
counter++;
}
destination[counter] = '/0';
}
int main(){
}
is my edited code but now the testbed says that it is taking too long and crashes.
Arrays in C++ have an interesting property where they can easily decay to pointers.
destination += source[counter]; does not append source[counter] to the end of destination.
Instead, destination has decayed to a pointer and this operation is doing pointer arithmatic on destination.
Instead, you want to do destination[destinationLocation] = source[counter]; to actually set the character in destination.
Don't forget to set destination[end] = '\0'; at the end to null terminate the destination array.
One final thing to watch out for is that C++ will not make sure that your arrays are properly sized. If destination is not of the proper size, the code will fail at run time with a segmentation fault.
For future reference, you might want to look into using C++'s std::vector class. std::vector is a variable sized array-like container which automatically keeps track of its size and memory usage. Using pure arrays in C++ is sometimes difficult and error prone (as you have just seen), so std::vector can make things easier.
Static arrays are a fixed sized in C++. That means you can't extend or shrink them at all under any circumstance.
There are three main alternatives to achieve what you're trying to do. From your code, it looks like the best one would be to use the std::string class (since you're using chars). It contains all the code to manage and concatenate the data very easily.
If you absolutely need an array, then std::vector would be the next best choice. It allows push and pop operations etc., and will automatically resize the underlying dynamic array as needed.
Finally, you could use a dynamic array directly. You would create and destroy it using new [] and delete []. When you need to extend the array, you need to create a new one with the new size, copy the old data over, and destroy the old one. It's a lot of unnecessary extra work though, so the other two options are much better.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Why this fragment of code does not work? I know that all entered strings have length less than 20 symbols.I do not use std::string because I want to learn how to use char*
#include <map>
#include <stdio.h>
using namespace std;
map <char*,int> cnt;
int main()
{
char ans[20];
int n,mx = 0;
scanf("%d\n",&n);
for ( int i = 1; i <= n; i++){
char str[20];
gets(str);
cnt[str]++;
}
for ( auto i = cnt.begin(); i != cnt.end(); i++ )
puts(i->first);
}
Let's be clear that your code has a lot of undefined behavior. I tried running your code and here is what I saw on my machine. You should tell us what your behavior was though because it's impossible to say what's going on for you otherwise.
First off, here was my program input.
3
hello
world
cat
And the output...
cat
char str[20] is a memory address, and that address is being reused by the compiler. Let's say that memory address is 0xABCD.
So on the first iteration, the map contains one element which is { 0xABCD, 1 }. On the second iteration it contains the same element with its value incremented, {0xABCD, 2}. On the third iteration it contains {0xABCD, 3}. Then when you go to print the map, it finds only one element in the map, and prints that memory address. This memory address happens to contain the word "cat", so it prints cat.
But this behavior is not reliable. The array char str[20] doesn't exist outside of the for loop, so sticking it into map <char *, int> cnt and even worse printing the array outside the loop are both undefined behavior.
If you want your code to work, I suppose you could do this....
for ( int i = 1; i <= n; i++){
char * str = new char[20];
gets(str);
cnt[str]++;
}
for ( auto i = cnt.begin(); i != cnt.end(); i++ )
puts(i->first);
for ( auto i = cnt.begin(); i != cnt.end(); i++ )
delete[](i->first);
But really, the correct strategy here is to either....
1) Use std::string
or
2) Don't use std::map
If you want to use C strings beyond converting them to std::string, then program without the use of the C++ std library. Stick to the C standard library.
Seems like cnt is std::map<char*, ...>. When you do cnt[str] you use pointer to local variable str as key, but str is only valid during single iteration. After that str is freed (semantically, optimizer may reuse it, but it is irrelevant here) and pointer to it is no longer valid.
It's very simple: when you allocate a C-style array as a local variable (char str[20];), it is allocated on the stack. It behaves just like any other object that you allocate as a local variable. And when it falls out of scope, it will be destroyed.
When you try to pass the array to the map in cnt[str], the array name decays to a pointer to the first element (it implicitely converts an expression of type char[20] into an expression of type char*). This is something radically different than an array. The map only ever sees this single pointer and stores it as the key. The map does not dereference the pointer to find out what's behind it, it just uses the memory location.
To fix your code, you need to do two things:
You need to allocate memory for your strings on the heap, so that the char* remains valid after the end of the scope. The easiest way to do this is to use the getline() or getdelim() functions available in the POSIX-2008 standard: These beautiful two functions will actually do the malloc() call for you. However, you still need to remember to free the string afterwards.
Making the map aware that you are talking about strings and not about memory addresses is much harder to achieve. If you must use a map, you likely need to define your own std::string-like wrapper class. But I guess, since you are playing around with the char* to learn their use, it would be more prudent to use some other kind of list and program the logic to check whether the given string is already in the list. Could be an array of char*, probably sorted to save lookup time, or a linked list, or whatever you like. For ease, you can just use an std::vector<char*>, but don't forget to free your strings before letting the vector fall out of scope.
I have a large char array which is functioning as a memory pool and want to store a pointer in the first position of the array which points to whatever the next open position in the pool is, so every time something is allocated to the pool the pointer would point to the byte that follows the ones which were just allocated. My only problem is I am not quite sure how to store the pointer in the array and then be able to modify it in other functions since the only place the pointer will exist is in the array[0] position. Can anyone point me in the right direction on this?
the char array is declared like:
char pool[size];
What you really want is an index into that array that tells you where to insert.
You could declare a structure:
struct pool
{
char poolData[size];
int insertIndex;
};
So that you always have the pool memory and index where you want to insert to together. Or, just have a separate variable and pass them together to whoever needs to use it.
char pool[size];
int insertIndex;
There's no need to "hijack" the first element of the array and use it differently than the rest of the array; just declare another variable to track the state of the pool.
If you can't follow the recommendations of the other answers because you absolutely must use the pool to store all information in it, the safest way to store the integer information in the char-array is to use memcpy (I am using C++11 syntax):
#include <cstring>
#include <iostream>
int main()
{
using size_type = std::size_t;
static constexpr size_type size = 1000;
char pool[size];
/* Store 12 as integer information at the beginning
of the pool: */
size_type next_free = 12;
std::memcpy(pool,&next_free,sizeof(size_type));
/* Retrieve it: */
size_type retrieved = 0;
std::memcpy(&retrieved,pool,sizeof(size_type));
/* This will output 12: */
std::cout << retrieved << std::endl;
return 0;
}
Of course this implies that the first sizeof(size_type) entries of the pool must not be used to store any actual characters. The lowest entry you can actually use is pool[sizeof(size_type)].
I think what you need is an index to remember where is the next empty spot on the pool (initially will be zero).
char pool[size];
int index = 0;
Then everytime you insert a new element, you just increment it:
if(index < size) {
pool[index] = 123;
index++;
}
char **pPoolEnd = (char **) pool;
to initialize the pointer you want.
*pPoolEnd = pool + sizeof(char **);
to make it point to its own end (e.g. when there's nothing else in the pool).
However, why would you want to do this? It's confusing, error prone and probably unnecessary. Others have pointed to much better alternatives. Assuming I had such a pool in the first place, I would probably go with one of those, or simply use a separate pointer, char *poolEnd along with pool.
Also, it's bad style to expose your implementation details to users ("pool end pointer is at pool[0]") and even worse to expect them to deal with them ("please update pool[0] whenever you'd like to allocate from the pool"). Think malloc and free; expose simple function interfaces to your users.
I have a quick question regarding the scope of dynamic arrays, which I assume is causing a bug in a program I'm writing. This snippet checks a function parameter and branches to either the first or the second, depending on what the user passes.
When I run the program, however, I get a scope related error:
error: ‘Array’ was not declared in this scope
Unless my knowledge of C++ fails me, I know that variables created within a conditional fall out of scope when when the branch is finished. However, I dynamically allocated these arrays, so I cannot understand why I can't manipulate the arrays later in the program, since the pointer should remain.
//Prepare to store integers
if (flag == 1) {
int *Array;
Array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char *Array;
Array = new char[input.length()];
}
Can anyone shed some light on this?
Declare Array before if. And you can't declare array of different types as one variable, so I think you should use to pointers.
int *char_array = nullptr;
int *int_array = nullptr;
//Prepare to store integers
if (flag == 1) {
int_array = new int[input.length()];
}
//Prepare to store chars
else if (flag == 2) {
char_array = new char[input.length()];
}
if (char_array)
{
//do something with char_array
}
else if (int_array)
{
//do something with int_array
}
Also as j_random_hacker points, you might want to change you program design to avoid lot's of if
While you are right that since you dynamically allocated them on the heap, the memory won't be released to the system until you explicitly delete it (or the program ends), the pointer to the memory falls out of scope when the block it was declared in exits. Therefore, your pointer(s) need to exist at a wider scope if they will be used after the block.
The memory remains allocated (i.e. taking up valuable space), there's just no way to access it after the closing }, because at that point the program loses the ability to address it. To avoid this, you need to assign the pointer returned by new[] to a pointer variable declared in an outer scope.
As a separate issue, it looks as though you're trying to allocate memory of one of 2 different types. If you want to do this portably, you're obliged to either use a void * to hold the pointer, or (less commonly done) a union type containing a pointer of each type. Either way, you will need to maintain state information that lets the program know which kind of allocation has been made. Usually, wanting to do this is an indication of poor design, because every single access will require switching on this state information.
If I understand your intend correctly what you are trying to do is: depending on some logic allocate memory to store n elements of either int or char and then later in your function access that array as either int or char without the need for a single if statement.
If the above understanding is correct than the simple answer is: "C++ is a strong-typed language and what you want is not possible".
However... C++ is also an extremely powerful and flexible language, so here's what can be done:
Casting. Something like the following:
void * Array;
if(flag1) Array = new int[len]
else Array = new char[len];
// ... later in the function
if(flag) // access as int array
int i = ((int*)Array)[0];
Yes, this is ugly and you'll have to have those ifs sprinkled around the function. So here's an alternative: template
template<class T> T foo(size_t _len)
{
T* Array = new T[_len];
T element = Array[0];
return element;
}
Yet another, even more obscure way of doing things, could be the use of unions:
union int_or_char {int i; char c;};
int_or_char *Array = new int_or_char[len];
if(flag) // access as int
int element = Array[0].i;
But one way or the other (or the third) there's no way around the fact that the compiler has to know how to deal with the data you are trying to work with.
Turix's answer is right. You need to keep in mind that two things are being allocated here, The memory for the array and the memory when the location of the array is stored.
So even though the memory from the array is allocated from the heap and will be available to the code where ever required, the memory where the location of the array is stored (the Array variable) is allocated in the stack and will be lost as soon as it goes out of scope. Which in this case is when the if block end. You can't even use it in the else part of the same if.
Another different code suggestion from Andrew I would give is :
void *Array = nullptr;
if (flag == 1) {
Array = new int[input.length()];
} else if (flag == 2) {
Array = new char[input.length()];
}
Then you can directly use if as you intended.
This part I am not sure : In case you want to know if its an int or char you can use the typeid literal. Doesn't work, at least I can't get it to work.
Alternatively you can use your flag variable to guess what type it is.
I apologise if I'm completely misunderstanding C++ at the moment, so my question might be quite simple to solve. I'm trying to pass a character array into a function by value, create a new array of the same size and fill it with certain elements, and return that array from the function. This is the code I have so far:
char *breedMutation(char genome []){
size_t genes = sizeof(genome);
char * mutation = new char[genes];
for (size_t a = 0 ;a < genes; a++) {
mutation[a] = 'b';
}
return mutation;
}
The for loop is what updates the new array; right now, it's just dummy code, but hopefully the idea of the function is clear. When I call this function in main, however, I get an error of initializer fails to determine size of ‘mutation’. This is the code I have in main:
int main()
{
char target [] = "Das weisse leid"; //dummy message
char mutation [] = breedMutation(target);
return 0;
}
I need to learn more about pointers and character arrays, which I realise, but I'm trying to learn by example as well.
EDIT: This code, which I'm trying to modify for character arrays, is the basis for breedMutation.
int *f(size_t s){
int *ret=new int[s];
for (size_t a=0;a<s;a++)
ret[a]=a;
return ret;
}
Your error is because you can't declare mutation as a char[] and assign it the value of the char* being returned by breedMutation. If you want to do that, mutation should be declared as a char* and then deleted once you're done with it to avoid memory leaks in a real application.
Your breedMutation function, apart from dynamically allocating an array and returning it, is nothing like f. f simply creates an array of size s and fills each index in the array incrementally starting at 0. breedMutation would just fill the array with 'b' if you didn't have a logic error.
That error is that sizeof(genome); will return the size of a char*, which is generally 4 or 8 bytes on a common machine. You'll need to pass the size in as f does since arrays are demoted to pointers when passed to a function. However, with that snippet I don't see why you'd need to pass a char genome[] at all.
Also, in C++ you're better off using a container such as an std::vector or even std::array as opposed to dynamically allocated arrays (ones where you use new to create them) so that you don't have to worry about freeing them or keeping track of their size. In this case, std::string would be a good idea since it looks like you're trying to work with strings.
If you explain what exactly you're trying to do it might help us tell you how to go about your problem.
The line:
size_t genes = sizeof(genome);
will return the sizeof(char*) and not the number of elements in the genome array. You will need to pass the number of elements to the breedMutation() function:
breedMutation(target, strlen(target));
or find some other way of providing that information to the function.
Hope that helps.
EDIT: assuming it is the number of the elements in genome that you actually want.
Array are very limited.
Prefer to use std::vector (or std::string)
std::string breedMutation(std::string const& genome)
{
std::string mutation;
return mutation;
}
int main()
{
std::string target = "Das weisse leid"; //dummy message
std::string mutation = breedMutation(target);
}
Try replacing the second line of main() with:
char* mutation = breedMutation(target);
Also, don't forget to delete your mutation variable at the end.
void pushSynonyms (string synline, char matrizSinonimos [1024][1024]){
stringstream synstream(synline);
vector<int> synsAux;
int num;
while (synstream >> num) {synsAux.push_back(num);}
int index=0;
while (index<(synsAux.size()-1)){
int primerSinonimo=synsAux[index];
int segundoSinonimo=synsAux[++index];
matrizSinonimos[primerSinonimo][segundoSinonimo]='S';
matrizSinonimos [segundoSinonimo][primerSinonimo]='S';
}
}
and the call..
char matrizSinonimos[1024][1024];
pushSynonyms("1 7", matrizSinonimos)
It's important for me to pass matrizSinonimos by reference.
Edit: took away the & from &matrizSinonimos.
Edit: the runtime error is:
An unhandled win32 exception occurred in program.exe [2488]![alt text][1]
What's wrong with it
The code as you have it there - i can't find a bug. The only problem i spot is that if you provide no number at all, then this part will cause harm:
(synsAux.size()-1)
It will subtract one from 0u . That will wrap around, because size() returns an unsigned integer type. You will end up with a very big value, somewhere around 2^16 or 2^32. You should change the whole while condition to
while ((index+1) < synsAux.size())
You can try looking for a bug around the call side. Often it happens there is a buffer overflow or heap corruption somewhere before that, and the program crashes at a later point in the program as a result of that.
The argument and parameter stuff in it
Concerning the array and how it's passed, i think you do it alright. Although, you still pass the array by value. Maybe you already know it, but i will repeat it. You really pass a pointer to the first element of this array:
char matrizSinonimos[1024][1024];
A 2d array really is an array of arrays. The first lement of that array is an array, and a pointer to it is a pointer to an array. In that case, it is
char (*)[1024]
Even though in the parameter list you said that you accept an array of arrays, the compiler, as always, adjusts that and make it a pointer to the first element of such an array. So in reality, your function has the prototype, after the adjustments of the argument types by the compiler are done:
void pushSynonyms (string synline, char (*matrizSinonimos)[1024]);
Although often suggested, You cannot pass that array as a char**, because the called function needs the size of the inner dimension, to correctly address sub-dimensions at the right offsets. Working with a char** in the called function, and then writing something like matrizSinonimos[0][1], it will try to interpret the first sizeof(char**) characters of that array as a pointer, and will try to dereference a random memory location, then doing that a second time, if it didn't crash in between. Don't do that. It's also not relevant which size you had written in the outer dimension of that array. It rationalized away. Now, it's not really important to pass the array by reference. But if you want to, you have to change the whole thingn to
void pushSynonyms (string synline, char (&matrizSinonimos)[1024][1024]);
Passing by reference does not pass a pointer to the first element: All sizes of all dimensions are preserved, and the array object itself, rather than a value, is passed.
Arrays are passed as pointers - there's no need to do a pass-by-reference to them. If you declare your function to be:
void pushSynonyms(string synline, char matrizSinonimos[][1024]);
Your changes to the array will persist - arrays are never passed by value.
The exception is probably 0xC00000FD, or a stack overflow!
The problem is that you are creating a 1 MB array on the stack, which probably is too big.
try declaring it as:
void pushSynonyms (const string & synline, char *matrizSinonimos[1024] )
I believe that will do what you want to do. The way you have it, as others have said, creates a 1MB array on the stack. Also, changing synline from string to const string & eliminates pushing a full string copy onto the stack.
Also, I'd use some sort of class to encapsulate matrizSinonimos. Something like:
class ms
{
char m_martix[1024][1024];
public:
pushSynonyms( const string & synline );
}
then you don't have to pass it at all.
I'm at a loss for what's wrong with the code above, but if you can't get the array syntax to work, you can always do this:
void pushSynonyms (string synline, char *matrizSinonimos, int rowsize, int colsize )
{
// the code below is equivalent to
// char c = matrizSinonimos[a][b];
char c = matrizSinonimos( a*rowsize + b );
// you could also Assert( a < rowsize && b < colsize );
}
pushSynonyms( "1 7", matrizSinonimos, 1024, 1024 );
You could also replace rowsize and colsize with a #define SYNONYM_ARRAY_DIMENSION 1024 if it's known at compile time, which will make the multiplication step faster.
(edit 1) I forgot to answer your actual question. Well: after you've corrected the code to pass the array in the correct way (no incorrect indirection anymore), it seems most probable to me that you did not check you inputs correctly. You read from a stream, save it into a vector, but you never checked whether all the numbers you get there are actually in the correct range. (end edit 1)
First:
Using raw arrays may not be what you actually want. There are std::vector, or boost::array. The latter one is compile-time fixed-size array like a raw-array, but provides the C++ collection type-defs and methods, which is practical for generic (read: templatized) code.
And, using those classes there may be less confusion about type-safety, pass by reference, by value, or passing a pointer.
Second:
Arrays are passed as pointers, the pointer itself is passed by value.
Third:
You should allocate such big objects on the heap. The overhead of the heap-allocation is in such a case insignificant, and it will reduce the chance of running out of stack-space.
Fourth:
void someFunction(int array[10][10]);
really is:
(edit 2) Thanks to the comments:
void someFunction(int** array);
void someFunction(int (*array)[10]);
Hopefully I didn't screw up elsewhere....
(end edit 2)
The type-information to be a 10x10 array is lost. To get what you've probably meant, you need to write:
void someFunction(int (&array)[10][10]);
This way the compiler can check that on the caller side the array is actually a 10x10 array. You can then call the function like this:
int main() {
int array[10][10] = { 0 };
someFunction(array);
return 0;
}