I have a problem with memory access. When i = 0, Visual Studio throws an exception with reference to a line as labelled in the following code.
Can't access at 0x00AD8B3B and 0x00AD8B3B equals scr+np-i
How can I fix the for-loop body so as to fix this issue?
int o_strrev(char* scr)
{
int np = strlen(scr) - 1;
char tmp;
if (!scr) return -1;
if (!*scr) return -1;
for (int i = 0; i < np / 2; i++)
{
tmp = scr[np-i];
scr[np-i] = scr[i]; # this line
scr[i] = tmp;
}
return 0;
}
As pointed out by #Revolver_Ocelot, you are probably passing a const char* from a string literal. Since these are, by definition, constant, you can't modify them in the way you're trying to. You need some way to convert const char* into a non constant char*. Something along these lines will work for you:
string str = "string";
char* cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
I've compiled your code in g++ using non constant char* and it works fine. Just remember to deallocate your char* when you're done with it. We don't want memory leaks ;)
I see you are trying to reverse a string.
Might I suggest a simpler way
void reverse(char *string_var)
{
int length, c;
char *begin, *end, temp;
length = strlen(string_var);
begin = string_var;
end = string_var;
for (c = 0; c < length - 1; c++)
end++;
for (c = 0; c < length/2; c++)
{
temp = *end;
*end = *begin;
*begin = temp;
begin++;
end--;
}
}
Make sure you pass character array of the form
char word[64]
Or maybe by recursion
void reverse(char *x, int begin, int end)
{
char c;
if (begin >= end)
return;
c = *(x+begin);
*(x+begin) = *(x+end);
*(x+end) = c;
reverse(x, ++begin, --end);
}
You're most likely calling o_strrev with a string literal, some thing like:
o_strrev("This ain't gonna work!");
This will compile with most compilers and at most generate a warning. Try cranking up your warning level.
Instead, you want to make a dynamic copy of your string on the heap and work with a char* pointer to that, something like:
string str = "This is gonna work!!"
size_t len = str.size();
char* my_string = new char[len + 1];
strncpy(my_string, str.data(), len)
my_string[len] = '\0';
o_strrev(my_string);
// ...
delete[] my_string;
Related
When I run the program, I get exception "heap has been corrupted" after completion of the function
I have read that this exception may cause if you are using memory that has been freed, or when you are writing to index which is out of array index. But none of the cases applies here. I have read other answers of some problems but it didn't help much.
`char fileNametoExport[26]="d:\\FOlder1\\part1.ipt";
char WorkingFolderName[260] ="d:\\folder";
int start = rFind(fileNametoExport, '\\');
int finish = rFind(fileNametoExport, '.');
if (start == -1)
start = 0;
char partname[260];
strcpy(partname,substr(fileNametoExport, start, finish));
::AfxMessageBox((LPCTSTR)partname);
char xtfile[260];
char xmltxtfile[260];
strcpy(xtfile, strcat(WorkingFolderName, partname));
strcat(xtfile, "__Default.x_t");
strcpy(xmltxtfile, WorkingFolderName);
strcat(xmltxtfile,"_XT_SE_INV_Default_SOLID_0_Solid1_xt.xmt_txt");`
function rfind() to find occurence of char in char array-
int rFind(char* s, char c)
{
int sz = 0;
char *tmp = s;
while (*tmp != '\0')
{
sz++;
tmp++;
}
for (int i = sz - 1; i >= 0; i--)
{
if (*(s + i) == c)
return i;
}
return -1;
}
function substr() to get substring from position x to y (y exclusive)
char* substr(char* s, const int b, const int f)
{
char *str = new char[f - b];
int t = 0;
for (int i = b; i != f; i++)
{
str[t] = s[i];
t++;
}
str[t] = '\0';
return str;
}
P.S- While giving input I ensure that fileNametoExport always contains '.' and '\'.
Your program do not check lengths of input strings. You can receive a string longer than your buffer and program will fail.
If your program get fileNametoExport = "d:\\somefolder\\somefilewithoutdot" , finish will be -1 and program fail at strcpy(partname,substr(fileNametoExport, start, finish)); .
Program writes after buffer in char* substr(char* s, const int b, const int f) at line
str[t] = '\0';
because t at this point equal f-b , size of str buffer.
Function _ASSERTE( _CrtCheckMemory( ) ); from <crtdbg.h> very useful when searching for bugs like this. Put it around suspicious code and it fails after your bug. It works only in debug.
I'm dealing with dynamic arrays in C++. Help with the following code.
I'm trying to read the characters one by one and make the C-string. If the array size is not enough, I increase it. But the function increaseArray works with an error and returns a string with other characters. What I am wrong?
void increaseArray(char* str, int &size){
char* newStr = new char[size * 2];
for (int i = 0; i < size; i++){
newStr[i] = str[i];
}
size *= 2;
delete[] str;
str = newStr;
}
char* getline()
{
int size = 8;
char* str = new char[size];
char c;
int index = 0;
while (c = getchar()) {
if (index == size) increaseArray(str, size);
if (c == '\n') {
str[index] = '\0';
break;
};
str[index] = c;
index++;
}
return str;
}
In function increaseArray you are assigning newStr to str however str is local copy of pointer in increaseArray function thus change is not visible outside it.
Simplest fix is to change increaseArray signature to:
void increaseArray(char*& str, int &size)
So reference to pointer will be passed, thus changes to str inside increaseArray will be visible outside it.
You could do that.
Its simple..
#include <string.h>
#include <stdlib.h>
using namespace std;
void increaseArray(char* &str, int size){
str = (char *)realloc(str,size*2);
}
I am open to using intermediary C++ code, though C code is the preference.
I have code like the following:
char *fileName1 = "graph";
char *extension1 = ".eps";
I want to create a new char* variable called fileName1WithExtension1 which would correspond to "graph.eps", formed from the two char* variables given above. How can this be done?
If you use C++, have those as std::string strings:
std::string fileName1 = "graph";
std::string extension1 = ".eps";
And then simply
std::string fileName1WithExtension1 = filename1 + extension1;
If you then need to pass that to a C library function expecting a C string, get char pointer with fileName1WithExtension1.c_str()
There really is no reason to muck about with plain C strings in C++ code. It is so error-prone and tedious, that it should be actively avoided.
char *new_string;
new_string = malloc(strlen(fileName1) + strlen(extension1) + 1);
sprintf(new_string, "%s%s", fileName1, extension1);
...
free(new_string)
You can use the asprintf() function
char *buffer;
asprintf (&buffer, "%s%s", fileName1, extension1);
When the buffer variable become useless in your code, you have to free the memory allocated for buffer by asprintf with
free(buffer);
char *joined;
joined = (char*)malloc(strlen(fileName1) + strlen(extension1) + 1);
strcpy(joined, fileName1)
strcat(joined, extension1)
For a small performance increase, if the compiler is smart enough at optimizing, change the last line to
strcpy(joined+strlen(fileName1), extension1)
Even better, store the length of fileName1 in a variable the first time you determine it, and use it in the final strcpy().
If you want to go REALLY low-level, with ugly loops and such, you can do this: (Tested, it compiles and gives the expected and desired results)
char* filename1 = "graph";
char* extension1 = ".eps";
char* filename1WithExtension1 = combine(filename1, extension1);
where:
char* combine(char* str1, char* str2)
{
int str1len = 0, str2len = 0;
while(str1[str1len] != '\0') {
str1len++;
}
while(str2[str2len] != '\0') {
str2len++;
}
int outputlen = str1len + str2len + 1;
char* output = new char[outputlen];
for(int i = 0; i < str1len; i++)
{
output[i] = str1[i];
}
for(int i = str1len; i < outputlen; i++)
{
output[i] = str2[i - str1len];
}
return output;
}
I did a bit of C brush-up for fun, here's an alternative (C90 and C++ compatible code) for joining an array of C strings with separator. It should be very efficient with any decently optimizing compiler, too:
#include <string.h>
#include <stdlib.h>
/* **parts are strings to join, a NULL-terminated array of char*
* sep is separator string, use "" for no separator, must not be NULL
* returns malloc-allocated buffer which must be freed
* if len_out!=NULL, sets *len_out to strlen of result string */
char *astrjoin(int *len_out, const char *sep, char **parts) {
int part_count;
int parts_total_len = 0;
for(part_count = 0; parts[part_count]; ++part_count) {
parts_total_len += strlen(parts[part_count]);
}
if (part_count > 0) {
int malloc_size = (part_count - 1) * strlen(sep) + parts_total_len + 1;
char *result = (char*)malloc(malloc_size);
char *dest = result;
for(;;) {
const char *src;
for(src=*parts; *src; ++src) *dest++ = *src;
if (!*++parts) break;
for(src=sep ; *src; ++src) *dest++ = *src;
}
*dest = 0;
if (len_out) *len_out = malloc_size - 1;
return result;
} else {
if (len_out) *len_out = 0;
return strdup("");
}
}
Example usage:
int main(int argc, char *argv[]) {
/* argv is NULL-terminated array of char pointers */
char *commandline = astrjoin(NULL, " ", argv);
printf("argc: %d\nargv: %s\n", argc, commandline);
free(commandline);
return 0;
}
To call that in context of your question, it could be something like:
char *tmparr[] = { fileName1, exteansion1, NULL };
char *fileName1WithExtension1 = astrjoin(NULL, "", tmparr);
It would be trivial to create a version with sep and/or len_out dropped, or a version supporting "varargs", with signature looking something like:
char *astrjoin_va(int *len_out, const char *sep, ...);
Which would be nicer to call in context of your question:
char *fileName1WithExtension1 = astrjoin_va(NULL, "", fileName1, extension1, NULL);
Can someone tell me what's wrong with the following?
I'm trying to add characters to a character array. name is a pointer to a character array in the MyString class.
void MyString::add_chars(char* c)
{
if(l < strlen(c)+strlen(name))
name = resize(name, l, sizeof(c));
int i,j;
for(i=0; i<strlen(c); i++) {
name[i+l-1] = c[i];
l++;
}
}
char* MyString::resize(char* vptr, int currentsize, int extra) {
char* temp = new char[currentsize + extra];
int i;
for (i = 0; i < currentsize; i++) {
temp[i] = vptr[i];
}
vptr = temp;
return vptr;
}
And in main:
MyString g ("and");
g.add_chars("baasdf");
cout << g.get_name() << "\n";
But get_name returns "andb". How can I fix my code?
Edit:
Updated code, still same result..
void StringList::add_chars(char* c)
{
char* my_new_string = resize(name, l, sizeof(char));
if( my_new_string != NULL )
{
delete [] name;
name = my_new_string;
}
int i,j;
for(i=0; i<strlen(c); i++) {
name[i+l-1] = c[i];
l++;
}
name[l-1] = '\0';
}
char* StringList::resize(char* vptr, int currentsize, int extra) {
char* temp = new char[currentsize + extra + 1];
int i;
for (i = 0; i < currentsize; i++) {
temp[i] = vptr[i];
}
vptr = temp;
return vptr;
}
This line is wrong:
name = resize(name, l, sizeof(c));
You should not take the sizeof(char*), which your c variable is, but you should do sizeof(char) or just 1.
Also, make sure that you do +1 on the size to take care of the zero termination char at the end of your string.
How can I fix my code?
Don't fix it. Throw it away and use vector<char> or just string.
But I insist, how can I fix my code!?
OK, OK, here is how...
Get a nice debugger, for example this one.
Step carefully through the code, constantly inspecting the variables and comparing them with what you expect them to be.
When you reach the call to resize, take note of sizeof(c) (assigned to extra parameter of resize). When you realize it is not what you expected, ask yourself: what is the purpose of sizeof, and you'll understand why.
BTW, you also have a memory leak and a very poor performance due all these strlens.
Firstly, am I right in assuming that this is a learning exercise for you in learning "how to create your own string class"? C++ has already got a built-in string type which you should always prefer for the most part.
the sizeof operator yields the size (in bytes) of its operand, which in this case is c whose type is char* - it looks like what you're actually after is the length of a null-terminated character array (a "C" string") - you're already using strlen, so I'd suggest you simply want to use that again. (taking a null-terminator into account too)
name = resize(name, l, strlen(c) + 1);
Note, that your code looks as if it suffers from memory leaks. You're assigning a new value to your name variable without clearing up whatever existed there first.
if(l < strlen(c)+strlen(name))
{
char* my_new_string = resize(name, l, strlen(c));
if( my_new_string != NULL )
{
delete [] name;
name = my_new_string;
}
}
EDIT: As other replies have pointed out, there's still plenty wrong with the code which could be resolved using C++'s string and vector.
Here's one possible way you could implement add_chars
void MyString::add_chars(char* c)
{
if( c != NULL && name != NULL )
{
size_t newlength = strlen(c) + strlen(name) + 1;
char* newstring = new char[newlength];
if( newstring != NULL )
{
size_t namelength = strlen(name);
size_t remaining = newlength - namelength;
strncpy( newstring, name, newlength );
strncpy( &newstring[namelength] , c, remaining );
delete [] name;
name = newstring;
}
}
}
How would I manually concatenate two char arrays without using the strncpy function?
Can I just say char1 + char2?
Or would I have to write a for loop to get individual elements and add them like this:
addchar[0] = char1[0];
addchar[1] = char1[1];
etc
etc
addchar[n] = char2[0];
addchar[n+1] = char2[1];
etc
etc
To clarify, if
char1 = "happy"
char2 = "birthday"
I want addchar to = happybirthday
For a C-only solution use strncat:
char destination[80] = "";
char string1[] = "Hello";
char string2[] = " World!";
/* Copy string1 to destination */
strncat(destination, string1, sizeof(destination));
/* Append string2 to destination */
strncat(destination, string2, sizeof(destination) - sizeof(string1));
Note that the strn* family of string functions are safer than the ones without n, because they avoid the possibility of buffer overruns.
For a C++ solution, simply use std::string and operator+ or operator+=:
std::string destination("Hello ");
destination += "World";
destination += '!';
If you consider two trivial loops to be "manual", then yes, without using the standard library this is the only way.
char *append(const char *a, const char *b) {
int i = 0;
size_t na = strlen(a);
size_t nb = strlen(b);
char *r = (char*)calloc(na + nb + 1, 1);
for (i = 0; i < na; i++) {
r[i] = a[i];
}
for (i = 0; i < nb; i++) {
r[na + i] = b[i];
}
return r;
}
Remember to call free.
If you're using c++ just use an std::string. With std::strings, the + operator is supported, so you can do string1+string2.
Without using library functions, here is the procedure:
1. Point to the first character in string1.
2. While the current character at the pointer is not null, increment the pointer.
3. Create a "source" pointer pointing to string2.
4. While the character at the "source" location is not null:
4.1. Copy the character from the "source" location to the location pointed to by the String1 pointer.
4.2. Increment both pointers.
Unless this is homework, use C++ std::string for your text.
If you must use C style strings, use the library functions.
Library functions are optimized and validated, reducing your development time.
Alright, you want something like this:
char1 + char2
First, let's see the insane solution:
C:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = (char*)malloc(length);
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
C++:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length_left = strlen(a_Left);
unsigned int length_right = strlen(a_Right);
unsigned int length = length_left + length_right;
char* result = new char[length];
// clear the string
memset(result, 0, length);
// copy the left part to the final string
memcpy(result, a_Left, length_left);
// append the right part the to the final string
memcpy(&result[length_left], a_Right, length_right);
// make sure the string actually ends
result[length] = 0;
return result;
}
Now, let's see the sane solution:
char* StringAdd(char* a_Left, char* a_Right)
{
unsigned int length = strlen(a_Left) + strlen(a_Right);
char* result = new char[length];
strcpy(result, a_Left);
strcat(result, a_Right);
return result;
}
So, was this homework? I don't really care.
If it was, ask yourself: what did you learn?