_mkdir strange behaviour c++ - c++

I'm struggling with a strange issue.
I want to create a folder for the solution of my program and I've written the following code:
timer = time(NULL);
path.assign(".\\Solution_");
path.append(ctime(&timer));
ch1 = ':';
ch2 = '_';
for (i = 0; i < path.length(); ++i) {
if (path[i] == ch1 || path[i] == ' ')
path[i] = ch2;
}
mkdir(path.c_str());
it doesn't create anything even if path is equal to ".\Solution_Thu_Jun_12_10_10_31_2014" and if I type
mkdir(".\\test");
It works correctly.
I did many test and I ckeck all I could but I cannot figure out what's wrong.
Can anyone help me please?
Best,
Roberto
Detail:
Even if I use mkdir(path.c_str()); with path equal to "Solution_Thu_Jun_12_11_52_04_2014" (without any \) it doesn't work anyway and on the other side 'mkdir("test");' works.
Solution:
Ok there was a hidden newline.
Thanks everyone for the help :-)!!!

The issue you are having is that the backslash character is the start of an escape sequence. These were used to input a non-printable character into the stream (tabs, carriage returns, etc.).
So your program is seeing a backslash and expecting that the next character will be a command character. If it sees another backslash then it knows that you want a backslash and not an escape sequence, hence why \\ works and \ doesn't.
Since you are running a flavour of Windows you could use CreateDirectory function.
Also what you have put as your example is C, not C++. What source are you learning from?

Check if there is newline or any other illegal character for filename in windows. Your error looks like that.
windows doesn't allow these character <>?/\| or newline in filename

Related

iso c++ forbids comparison between pointer and integer, if statement comparing with a letter [duplicate]

Attempting to check the first character of a string to see if it contains a "/".
string pathname = "/test";
if(pathname.at(0) == "/")
{
// if first character is a slash then delete the slash
// but only delete the slash if it's the first character
pathname.erase(pathname.begin()+0);
}
I understand that the above code will not work because pathname.at(0) is considered an int.
I'm sure this has been asked before. But I have looked around a lot. I've seen the substr method the find method and many others. I can't seem to get them working right though.
Suggestions? Thanks in advance.
Use single quote for character constant.
if(pathname.at(0) == '/')
^ ^
Double quotes, no matter how many characters are inside, represents a C-style string. You can't compare a character to a C-string.
You compare the first symbol code with a pointer to string. Try to compare the first symbol with the char.
if(pathname.at(0) == '/')

Find first character of string, then compare it with a symbol c++

Attempting to check the first character of a string to see if it contains a "/".
string pathname = "/test";
if(pathname.at(0) == "/")
{
// if first character is a slash then delete the slash
// but only delete the slash if it's the first character
pathname.erase(pathname.begin()+0);
}
I understand that the above code will not work because pathname.at(0) is considered an int.
I'm sure this has been asked before. But I have looked around a lot. I've seen the substr method the find method and many others. I can't seem to get them working right though.
Suggestions? Thanks in advance.
Use single quote for character constant.
if(pathname.at(0) == '/')
^ ^
Double quotes, no matter how many characters are inside, represents a C-style string. You can't compare a character to a C-string.
You compare the first symbol code with a pointer to string. Try to compare the first symbol with the char.
if(pathname.at(0) == '/')

Strategy to replace spaces in string

I need to store a string replacing its spaces with some character. When I retrieve it back I need to replace the character with spaces again. I have thought of this strategy while storing I will replace (space with _a) and (_a with _aa) and while retrieving will replace (_a with space) and (_aa with _a). i.e even if the user enters _a in the string it will be handled. But I dont think this is a good strategy. Please let me know if anyone has a better one?
Replacing spaces with something is a problem when something is already in the string. Why don't you simply encode the string - there are many ways to do that, one is to convert all characters to hexadecimal.
For instance
Hello world!
is encoded as
48656c6c6f20776f726c6421
The space is 0x20. Then you simply decode back (hex to ascii) the string.
This way there are no space in the encoded string.
-- Edit - optimization --
You replace all % and all spaces in the string with %xx where xx is the hex code of the character.
For instance
Wine having 12% alcohol
becomes
Wine%20having%2012%25%20alcohol
%20 is space
%25 is the % character
This way, neither % nor (space) are a problem anymore - Decoding is easy.
Encoding algorithm
- replace all `%` with `%25`
- replace all ` ` with `%20`
Decoding algorithm
- replace all `%xx` with the character having `xx` as hex code
(You may even optimize more since you need to encode only two characters: use %1 for % and %2 for , but I recommend the %xx solution as it is more portable - and may be utilized later on if you need to code more characters)
I'm not sure your solution will work. When reading, how would you
distinguish between strings that were orginally " a" and strings that
were originally "_a": if I understand correctly, both will end up
"_aa".
In general, given a situation were a specific set of characters cannot
appear as such, but must be encoded, the solution is to choose one of
allowed characters as an "escape" character, remove it from the set of
allowed characters, and encode all of the forbidden characters
(including the escape character) as a two (or more) character sequence
starting with the escape character. In C++, for example, a new line is
not allowed in a string or character literal. The escape character is
\; because of that, it must be encoded as an escape sequence as well.
So we have "\n" for a new line (the choice of n is arbitrary), and
"\\" for a \. (The choice of \ for the second character is also
arbitrary, but it is fairly usual to use the escape character, escaped,
to represent itself.) In your case, if you want to use _ as the
escape character, and "_a" to represent a space, the logical choice
would be "__" to represent a _ (but I'd suggest something a little
more visually suggestive—maybe ^ as the escape, with "^_" for
a space and "^^" for a ^). When reading, anytime you see the escape
character, the following character must be mapped (and if it isn't one
of the predefined mappings, the input text is in error). This is simple
to implement, and very reliable; about the only disadvantage is that in
an extreme case, it can double the size of your string.
You want to implement this using C/C++? I think you should split your string into multiple part, separated by space.
If your string is like this : "a__b" (multiple space continuous), it will be splited into:
sub[0] = "a";
sub[1] = "";
sub[2] = "b";
Hope this will help!
With a normal string, using X characters, you cannot write or encode a string with x-1 using only 1 character/input character.
You can use a combination of 2 chars to replace a given character (this is exactly what you are trying in your example).
To do this, loop through your string to count the appearances of a space combined with its length, make a new character array and replace these spaces with "//" this is just an example though. The problem with this approach is that you cannot have "//" in your input string.
Another approach would be to use a rarely used char, for example "^" to replace the spaces.
The last approach, popular in a combination of these two approaches. It is used in unix, and php to have syntax character as a literal in a string. If you want to have a " " ", you simply write it as \" etc.
Why don't you use Replace function
String* stringWithoutSpace= stringWithSpace->Replace(S" ", S"replacementCharOrText");
So now stringWithoutSpace contains no spaces. When you want to put those spaces back,
String* stringWithSpacesBack= stringWithoutSpace ->Replace(S"replacementCharOrText", S" ");
I think just coding to ascii hexadecimal is a neat idea, but of course doubles the amount of storage needed.
If you want to do this using less memory, then you will need two-letter sequences, and have to be careful that you can go back easily.
You could e.g. replace blank by _a, but you also need to take care of your escape character _. To do this, replace every _ by __ (two underscores). You need to scan through the string once and do both replacements simultaneously.
This way, in the resulting text all original underscores will be doubled, and the only other occurence of an underscore will be in the combination _a. You can safely translate this back. Whenever you see an underscore, you need a lookahed of 1 and see what follows. If an a follows, then this was a blank before. If _ follows, then it was an underscore before.
Note that the point is to replace your escape character (_) in the original string, and not the character sequence to which you map the blank. Your idea with replacing _a breaks. as you do not know if _aa was originally _a or a (blank followed by a).
I'm guessing that there is more to this question than appears; for example, that you the strings you are storing must not only be free of spaces, but they must also look like words or some such. You should be clear about your requirements (and you might consider satisfying the curiosity of the spectators by explaining why you need to do such things.)
Edit: As JamesKanze points out in a comment, the following won't work in the case where you can have more than one consecutive space. But I'll leave it here anyway, for historical reference. (I modified it to compress consecutive spaces, so it at least produces unambiguous output.)
std::string out;
char prev = 0;
for (char ch : in) {
if (ch == ' ') {
if (prev != ' ') out.push_back('_');
} else {
if (prev == '_' && ch != '_') out.push_back('_');
out.push_back(ch);
}
prev = ch;
}
if (prev == '_') out.push_back('_');

Will istream::get() with no parameters return whitespace?

This seems like a really simple question, but I can't find the answer anywhere. If I'm parsing a file (that includes newline characters) character by character, using
char next = file.get();
will the following check ever be true?
if (next == '\n')
Yes. It gets the next character from the stream. It does not skip newlines or whitespace.

GNU readline whitespace quoting

i´m working on an application which uses readline to read commands from stdin.
It accepts "cd", and other commands which require a path as an argument. I'm having troubles with paths that include whitespaces. My objective is to somehow make readline quote the whitespaces, and autocomplete the path name after this character appears(actually, when a space is encountered, it is just skipped, and autocompletion starts from the next word).
I've been trying to achieve this, but i keep trying things and none of them work. I've managed to quote a " " into a "\ ", which is what i want. But then readline doesn't interpret this as part of the path, it just skips it, and autocompletes the next word as if there was nothing before that. Basically, i'm expecting the same behaviour as bash's autocompletion.
Any help is appreciated.
Thanks in advance!
Edit:
Alright, so i've managed to somehow accomplish what i was looking for. What i did was:
During initialization:
rl_attempted_completion_function = completition;
rl_completer_quote_characters = "\"";
rl_filename_quote_characters = " ";
completition should return a char** containing every command that matches what "text" as so far. I've ommitted that part, since it doesn't have to do with what i was asking. The important part is the rl_filename_quoting_desired = 1; which tells readline that you want your filenames to be quoted.
char **completition(const char *text, int start, int end) {
rl_filename_quoting_desired = 1;
return 0;
}
Note that what i ended up doing is what BuHHu-nyx said, just adding double quotes(") to filenames.
Try to escape not spaces but the whole path. For example:
cd "/path/to/some where"