Why is this string being mysteriously modified? - c++

Please forgive me if the answer to this is simple, but I have NO idea what is causing this. The PathCombineA function is somehow modifying the mypath variable. If you run the program you will see what I mean. (You must link Shlwapi.lib)
#include <Windows.h>
#include <Shlwapi.h>
#include <iostream>
using namespace std;
int main()
{
CHAR temp[MAX_PATH];
CHAR mypath[MAX_PATH];
GetModuleFileNameA(NULL, mypath, MAX_PATH);
GetTempPathA(MAX_PATH, temp);
LPSTR name = PathFindFileNameA(mypath);
cout << mypath << endl;
PathCombineA(name, temp, name);
cout << mypath << endl;
getchar();
return 0;
}
Output before PathCombineA
C:\Users\Owner\Desktop\etc\Debug\etc.exe
Output after PathCombineA
C:\Users\Owner\Desktop\etc\Debug\C:\Users\Owner\AppData\Local\Temp\etc.exe
If you guys have any idea what is going on, please tell me!
Thanks!

PathFindFileNameA is returning a pointer to the last part of the string in mypath.
You then pass that pointer into the mystring buffer as the output parameter to PathCombineA.
If you don't want mystring to be modified, you'll need yet another buffer to hold the output of PathCombineA.

Related

c++ cstring, Is there any way to get single char from cstring?

char cstri[] = "hello world";
From here, is there any way to get a single char, such as the first e, position at 1, from this cstring?
I tried a few times, and every time it returns the entire string starting from the passed index. So, if I want 'e', position at 1, it returns ello world instead of just e.
I also tried to copy a single char from the string using strncpy() and memcpy(), but it copies the string from index 0 to null, or just the specified amount.
strncpy(b, cstri , 1);
I know a cstring is read-only, but is there no way to get a single char from a cstring?
I want to use printf(), so I can't use char b = cstri[1]
Your question already hints on "C++" and given the additional fact that there is no difference in the memory representation of a C++ std::string and a normal c-string, the answer is simple: just learn how std::string works. Btw. std::string::c_str() then return your nice c-string.
#include <string>
#include <iostream>
int main() {
std::string hw = "hello world";
std::cout << hw << std::endl; // output: "hello world"
std::cout << hw.c_str() << std::endl; // output: "hello world"
std::cout << hw[1] << std::endl; // output: 'e'
return 0;
}
But there are a ton of more features of std::string and also look at what #include <iomanip> can do.

Character Array of dynamic length

I have written a C++ Function which can be represented as below:
All it does is take a string (this is where it crashes) and reverse it.
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
int main()
{
cout<<"Enter a string: "<<endl;
char *str;
gets(str);
cout<<"Reversed String is: ";
for(int i=strlen(str)-1;i>=0;i--)
cout<<(str[i]);
return 0;
}
I guess there's some kind of memory access violation.
Any clue why this doesn't work?
Error: Segmentation fault (core dumped)
In c++ there is way more easier and less error prone solution to this problem via std::reverse from algorithm. Also its easier to use std::string.
#include <iostream>
#include <algorithm>
int main ()
{
std::string input;
std::cout << "Enter string to reverse: ";
std::cin >> input;
std::reverse(input.begin(),input.end());
std::cout << "Reversed string: " << input << std::endl;
return 0;
}
If you have to do it via char arrays, try this (you dont even need dynamic memory allocation)
#include <iostream>
#include <algorithm>
#include <cstring>
int main ()
{
char input[1024];
puts("Enter string to reverse: ");
fgets(input, 1024, stdin);
std::reverse(input, input + strlen(input));
printf("Reversed string: %s", input);
return 0;
}
Your code isn't c++ style and I recommend you take a look at the answer from Filip (https://stackoverflow.com/a/45903067/4386427)
I'll just address what goes wrong with your code.
When you do
char* str;
all you get is a pointer that can point to a char. You don't get any memory for holding a char. Further the value of the pointer variable str is uninitialized.
So when you do
strlen(str)
you read an uninitialized variable and try to treat this uninitialized value as a C-style string. That is undefined behavior and is very likely to cause a program crash.
You need to make sure that str is initialized before using it. As you want dynamic memory, you could do:
char *str;
str = new(char[100]); // Initialize str to point to a dynamic allocated
// char array with size 100
...
...
delete(str);
But again - I wouldn't use this style in c++ code

Error: C++ literal memory mishandling

I have tried a lot to debug my code but it is still not working.The whole code just crashes but there is no allover error I am presenting the code please try to debug that one.
Code:
#include <iostream>
#include<conio.h>
#include<string.h>
#include<fstream>
using namespace std;
void write(char fname[],char text[])
{
strcat(fname,".txt");
ofstream w(fname,ios::app);
w<<text;
w<<"\n";
w.flush();
w.close();
cout<<" sippy "<<fname<<" ";
}
int main ()
{
int login=0;
char t[100],id[100]="Its id ",pass[100]="Its password";
login=1;
strcpy(t,id);
strcat(t,"\n");
strcat(t,pass);
cout<<" finally ";
write("database",t);
getch();
strcpy(t,id);
getch();
cout<<t<<" showing t here";
getch();
cout<<" hope this works for now ";
getch();
cout<<"\nEnter the text"<<endl;
write(id,t);
}
The above mentioned code does not work on tdm gcc code blocks
Edit 1:
Ok so now the major problem has been detected it is a minor bug usually caused because of drawback of a bad programming style. As it is often suggested that if a string is passed to a function then that particular function allocates a new string at the memory of the passed string. Since the passed string is a literal the code editing the newly formed string would try to edit a read only literal memory which is an error
Literals are read only because if compiler finds the use of same literal at some different place then it would be able to use same memory to flash the contents of literal therefore it becomes a necessity to make a literal read only and use of c-style string carefully(rather std::string should be used)
Thanks to all
If you are facing a SegFault I think this line could be the problem :
write("database",t);
because in your write function you use strcat on fname but you pass a read-only string.
Also, I think it might be best to use real c++ instead of c+ like :
#include <string>
#include <iostream>
#include <fstream>
void my_write(std::sting & fname, std::string & text) {
std::string file = fname + ".txt";
std::osftream w(file, std::ios::app);
w << text << "\n";
w.flush();
w.close();
}
int main() {
std::string t = "";
std::string id = "Its id";
std::string pass = "Its password";
std::string fname = "database";
int login = 1;
t = id + "\n" + pass;
my_write( fname, t);
}
I haven't test it but the idea is here.

convert single back slash to double back slash in c++

I have one path e.g. "C:\home\my folder". I want to convert it into "C:\\home\\my folder". Please suggest me how can i use any function call to do this?
Thanks in advance.
The best way to do this could be by using the Boost string algorithm library.
http://www.boost.org/doc/libs/1_46_1/doc/html/string_algo.html
Using the following command :
std::string newPath = boost::replace_all_copy(testStr, "\", "\\");
This would result in the replaced and newly formed string.
Hope this helps.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
ifstream lire("data.txt",ios::in);
string text ;
getline(lire,text); //text contains your repertory
cout<<text<<endl;
for (int i = 0 ; i < text.size();i++)
{
if(text[i] == '\\')
{
text.insert(i,"\\") ;
i++;
}
}
cout<<text<<endl;
return 0;
}
The following program works for me.
#include <iostream>
#include <string>
#include <Shlobj.h>
int main()
{
std::string myPath;
std::cout << "Enter path to create: ";
std::cin >> myPath;
std::cout << "Path from user: " << myPath << "\n";
::SHCreateDirectoryEx(nullptr, myPath.c_str(), nullptr);
return 0;
}
Sample Run
As you can see the path taken from user input only uses a single back slash but the directory is successfully created.
Enter path to create: C:\a_path
Path from user: C:\a_path
I think you chasing the wrong problem, assuming the reason you asked this question is because your call to the SHCreateDirectoryEx function failed.
Notes:
When some Win32 API functions fail (e.g., CraeateDirectory) you must call GetLastError to actually get the error code, but this isn't the case for SHCreateDirectoryEx (i.e., it returns the failure code directly).
The SHCreateDirectoryEx function also works for me if I use forward slashes.

File not showing last Character of string when written in file

This snippet is part of a big program. The problem I am facing is that when I write a string to the file using "write" member function, it do not show last character of string:
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
fstream file1("/users/xxxxxxx/desktop/file1.txt", ios::out);
string data;
cout << "Enter string: " << endl;
getline(cin, data);
file1.write(reinterpret_cast<char*>(&data), data.size());
//file1 << data;
file1.close();
return 0;
}
For Example: If Input String: "Hello World".
On File it will show: "Hello Worl",
But it does work fine if I input string using "file1 << data". Please help me in this
file1.write(reinterpret_cast<char*>(&data), data.size());
Don't do this, you are writing the string object itself to the file. if you really want to use write you have to get a pointer to the first char that the string holds, like this:
file1.write(data.data(), data.size());
Just use the << operator.
Why would you cast the address of a string into a char*? This isn't a meaningful conversion--you are casting a std::basic_string<char>* to char*. I suspect you want to treat string as char* since write accepts const char* as parameter. You can access the character sequence stored in your data by doing data.c_str().