I want to create folders in a directory by naming them in a sequence like myfolder1, myfolder2. i tried doing it with mkdir() function using a for loop but it doesn't take 'integer variables' and only takes 'const char values'. what to do now? is there any other function which do that or can mkdir() do that?
I'm not aware of any library calls that take an integer like you are asking. What you need to do is embed the number into the string before passing it to mkdir(). Since you tagged this question with 'c++' I've demonstrated a C++ oriented way of accomplishing this below.
#include <sstream> // for std::ostringstream
#include <string> // for std::string
const std::string baseFolderName = "myfolder";
for (int i = 1; i < 20; ++i)
{
std::ostringstream folderName;
folderName << baseFolderName << i;
mode_t mode = 0; //TBD: whatever is appropriate
mkdir(folderName.str().c_str(), mode);
}
If you really want this, you can use itoa(...)
Lets say
i = 20;
char buffer [33];
itoa (i,buffer,10); //10 means decimal
Now buffer = "20\0"
After this conversion you can add buffer to your default string.
So, all in all, you can use:
std::string str = "string";
char buffer[33] ;
itoa(20, buffer, 10);
str.append(buffer);
mkdir(str.c_str());
Related
I'm trying to base64 decode a string, then convert that value to a char array for later use. The decode works fine, but then I get garbage data when converting.
Here's the code I have so far:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
decodedChar[decodedData.size() + 1] = 0; // terminate the string
for (size_t i = 0; i < decodedData.size(); ++i) {
decodedChar[i] = decodedData[i];
}
vector<BYTE> is a typedef of unsigned char BYTE, as taken from this SO answer. The base64 code is also from this answer (the most upvoted answer, not the accepted answer).
When I run this code, I get the following value in the VisualStudio Text Visualiser:
TestStringÍ
I've also tried other conversion methods, such as:
char* decodedChar = reinterpret_cast< char *>(&decodedData[0]);
Which gives the following:
TestStringÍÍÍýýýýÝÝÝÝÝÝÝ*b4d“
Why am I getting the garbage data at the end of the string? What am i doing wrong?
EDIT: clarified which answer in the linked question I'm using
char* decodedChar;
decodedChar = new char[decodedData.size() +1]; // +1 for the final 0
Why would you manually allocate a buffer and then copy to it when you have std::string available that does this for you?
Just do:
std::string encodedData = "VGVzdFN0cmluZw=="; //"TestString"
std::vector<BYTE> decodedData = base64_decode(encodedData);
std::string decodedString { decodedData.begin(), decodedData.end() };
std::cout << decodedString << '\n';
If you need a char * out of this, just use .c_str()
const char* cstr = decodedString.c_str();
If you need to pass this on to a function that takes char* as input, for example:
void someFunc(char* data);
//...
//call site
someFunc( &decodedString[0] );
We have a TON of functions and abstractions and containers in C++ that were made to improve upon the C language, and so that programmers wouldn't have to write things by hand and make same mistakes every time they code. It would be best if we use those functionalities wherever we can to avoid raw loops or to do simple modifications like this.
You are writing beyond the last element of your allocated array, which can cause literally anything to happen (according to the C++ standard). You need decodedChar[decodedData.size()] = 0;
For testing purposes I would like each time I create a file name to add a number to it - the app I am testing has no user interface, and will likely create multiple files.
void somefunction()
{
static INT iFileNo = 0;
TCHAR tFileName[MAX_PATH] = L"c:/test/abcd.bmp";
iFileNo ++;
}
I would like to somehow append the iFileNo to the tFileName (to get something like abcd1.bmp, abcd2.bmp...)... How can I do that ?
Note: I am not using any string libraries
Minimal libraries... including
#include <STDLIB.H>
#include <STDIO.H>
#include <TCHAR.H>
Intended OS: Windows
You can make this hard, easy, or very easy. The middle of those would be something like:
void somefunction()
{
static unsigned int uiFileNo = 0;
static const WCHAR wSpec[] = L"c:/test/abcd%u.bmp";
WCHAR wFileName[MAX_PATH];
swprintf_s(wFileName, MAX_PATH, wSpec, uiFileNo++);
}
Uses swprintf_s, which would seem to fulfill your include-file restrictions (and assuming this is Windows, which your question seems to indicate).
Personally I's use std::wstring, but it appears you have reasons against it. Anyway, best of luck.
You've expressed a desire to not use any libraries. That's not a choice I would endorse, but since you asked...
The easiest way would be to decide on a fixed number of digits, with leading zeros. That makes the problem trivial. In this example I'm using two digits.
void somefunction()
{
static INT iFileNo = 0;
TCHAR tFileName[MAX_PATH] = L"c:/test/abcd00.bmp";
int iNumberOffset = 12;
if (iFileNo >= 100)
throw std::runtime_error("File number too large");
tFileName[iNumberOffset] += iFileNo / 10;
tFileName[iNumberOffset+1] += iFileNo % 10;
iFileNo ++;
}
You can use ostringstream:
std::ostringstream s;
s << "c:/test/abcd.bmp"
s << iFileNo++;
std::string filename = s.str();
If you want wide versions (as you're specifying L in your example) then use wstringstream and wstring.
If you really don't want to use a C++ library then you can use sprintf:
char filename[100];
sprint(filename, "c:/test/abcd.tmp-%d", iFileNo);
iFileNo++
You'll need to ensure that you buffer is big enough to hold the filename.
If you really don't want to use any libraries then Windows actually has it's own string formatting function, wsprintf which you can use instead of sprintf.
I am currently writing a program in C++. I want to save a number of files continuously throughout the run of my program. The format of the filename is as such:
char fnameC[sizeof "C:\..._SitTurn_104_c2_00_00_000.bmp"];
- SitTurn is an experiment name
- 104 is an experiment number
These two will be changing after each different run of the program. Currently, my program works like this:
char fnameCVS[sizeof"C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_SitTurn_104_c2_02.csv"];
LARGE_INTEGER frequency;
LARGE_INTEGER t1, t2;
double elapsedTime;
SYSTEMTIME comptime;
int main(int argc, char *argv[])
{
GetSystemTime(&comptime);
sprintf_s(fnameCVS, "C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_SitTurn_104_c2_%02d.csv", comptime.wDay);
However, I tried this and I can't seem to get it to work. Can anyone help me?
...//rest of code set up
string expName = "SitStand";
string subjNumber = "101";
char fnameCVS[sizeof "C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_" + expName + "_" + subjNumber + "_c2_02.csv"];
LARGE_INTEGER frequency;
LARGE_INTEGER t1, t2;
double elapsedTime;
SYSTEMTIME comptime;
int main(int argc, char *argv[])
{
GetSystemTime(&comptime);
sprintf_s(fnameCVS, "C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_" + expName + "_" + subjNumber + "_c2_%02d.csv", comptime.wDay);
Since I am using this filename later in the program also, I would like to be able to just rename all files by changing the two strings: expName and subjNumber. Can someone help me explain how I can name my files using a string inputs (e.g. expName and subjNumber), so I only have to rename those corresponding string each time I change the experiment name, or subject number. Thanks!
Try this:
char fnameCVS[MAX_PATH+1];
SYSTEMTIME comptime;
GetSystemTime(&comptime);
sprintf_s(fnameCVS, _countof(fnameCVS), "C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_SitTurn_104_c2_%02d.csv", comptime.wDay);
Or this:
#include <string>
#include <sstream>
std::string expName = "SitStand";
std::string subjNumber = "101";
std::string fnameCVS;
SYSTEMTIME comptime;
GetSystemTime(&comptime);
std::ostringstream oss;
oss << "C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_" << expName << "_" << subjNumber << "_c2_" << std::setw(2) << std::setfill('0') << comptime.wDay << ".csv";
fnameCVS = oss.str();
You are mixing sprintf and std::string, which is never a good plan. You should either pick to use C's sprintf with char *, or C++'s std::string with std::stringstream.
Your fnameCVS array isn't going to be big enough: you'll take the sizeof of a std::string, which almost certainly will not be what you want.
Option 1: Use only sprintf. Allocate a big-enough string (e.g. char fnameCVS[256]) and use snprintf(fnameCVS, 256, "...Skeleton_%s_%d_c2_%02.csv", ...).
Option 2: Use only string and use a std::stringstream to build your filename.
This is a really bad idea:
char fnameCVS[sizeof"C:\\Users\\Adam\\Desktop\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_RGBDepth_DataAcquisition2013\\Skeleton_SitTurn_104_c2_02.csv"];
The main reason is that it is very difficult to visually inspect whether you have allocated the right number of bytes. Perhaps you make a slight change to the filename later in the sprintf line but then you forget to update this line or you make a typo. Boom, buffer overflow (which may go undetected until it is time to give a presentation).
A secondary bug is that when you use %02d in printf, the 2 is a minimum field width; if the number would require more than 2 digits then it outputs more than 2 digits, causing a buffer overflow. To be safe here you'd need to check that the number is between 0 and 99 before printing it.
Finally, sprintf_s is a non-standard function, there's really no reason to use it instead of sprintf or snprintf.
In C++ the equivalent formatting is a bit more wordy, but leaves no possibility of buffer overflows:
std::string fnameCVS;
// ...
std::ostringstream oss;
oss << "C:\\Users\\whatever...." << std::setw(2) << std::setfill('0')
<< comptime.wDay;
fnameCVS = oss.str();
If you really want to stick with the printf family plus a static char array (note: you can use printf and a dynamically-sized char container) then to make your code safe:
char const my_format[] = "C:\\Users\\whatever.....\\%02d.csv";
char fnameCVS[ sizeof my_format - 2 ]; // "NN" is two chars shorter than "%02d"
// ...
if ( comptime.wDay < 0 || comptime.wDay > 99 )
throw std::runtime_error("wDay out of range");
snprintf(fnameCVS, sizeof fnameCVS, my_format, comptime.wDay);
Your update indicates that you want to compute various other parts of the filename at runtime too; the C++ version that I suggest is easier to extend than the C-with-static-array version where you have to calculate the amount of memory you need by hand.
I am working on an old app written in Visual C++ 6.0. I am trying to display an int variable in a MessageBox for debugging reasons. Here is my code, I thought this would be a simple process, but I am just learning C++. The two lines that are commented I have tried as well with similar errors. Below is the error I am getting.
int index1 = 1;
char test1 = index1;
// char var1[] = index1;
// char *varGo1 = index1;
MessageBox(NULL, test1, "testx", MB_OK);
error C2664: 'MessageBoxA' : cannot convert parameter 2 from 'char' to 'const char *'
Why bother with C-style strings if you tagged C++?
Although Mark Ransom provided MFC solution (which is perfectly valid), here is a Standard C++ one:
int index1 = 1;
std::string test1 = std::to_string(index1);
MessageBoxA(NULL, test1.c_str(), "testx", MB_OK);
References:
std::to_string();
Arrays are evil
Use boost::format for more sophisticated formatting.
int index1 = 1;
char buf[10];
itoa(index1,buf,10);
MessageBox(NULL,buf,"Caption",MB_OK);
Can try this
CString str1;
str1.Format(_T("%d"), index1);
MessageBox(NULL, str1, "testx", MB_OK);
CString's Format works just like printf to populate the string with the parameter list.
The second parameter of MessageBox needs to be a pointer to a string of chars, terminated with NULL. Passing a char will not work.
But, learning to use a debugger is an integral part to learning a language. Why not build a debug build and set a breakpoint on char test1 = index1; instead? You do that by pressing F9 when the cursor is on that line.
For what it's worth, I prefer to use a manipulator for this:
#include <sstream>
#include <iostream>
#include <windows.h>
using std::ostringstream;
using std::ostream;
ostream &msg_box(ostream &s) {
ostringstream &os = dynamic_cast<ostringstream &>(s);
MessageBox(NULL, os.str().c_str(), "testx", MB_OK);
return s;
}
int main() {
ostringstream msg;
msg << "The number is: " << 10 << msg_box;
return 0;
}
This maintains (mostly) the same interface nearly everybody's already accustomed to with iostreams, avoids the type-unsafe CString::Format, and avoids having several lines of distraction everywhere you're going to display a little information for debugging. The other obvious good point is that if you've overloaded operator<< for your own type, that overload will work with this as well.
Acording to your error, you should declare a const pointer on the second parameter.
Like this,
const char * test1= new char();
or use
std::string test1= "";
MessageBox(NULL, test1.c_str(), "testx", MB_OK);
Also using just "Text" will work.
Here is the pure C solution using sprintf method to store all input in buffer and passing that buffer to MessageBox.
#include <stdio.h>
#include <windows.h>
int main(void)
{
int intVal = 50;
float fltVal = 5.5;
char *str = "Test String";
char buf[1024] = {'\0'};//buffer to store formatted input.
//convert formatted input into buffer.
sprintf(buf,"Int value : %d\nFloat value : %f\nString : %s\n",intVal,fltVal,str);
//display whole buffer.
MessageBox(NULL,buf,"INFO",MB_ICONINFORMATION);
return 0;
}
i have a buffer
char buffer[size];
which i am using to store the file contents of a stream(suppose pStream here)
HRESULT hr = pStream->Read(buffer, size, &cbRead );
now i have all the contents of this stream in buffer which is of size(suppose size here). now i know that i have two strings
"<!doctortype html" and ".html>"
which are present somewhere (we don't their loctions) inside the stored contents of this buffer and i want to store just the contents of the buffer from the location
"<!doctortype html" to another string ".html>"
in to another buffer2[SizeWeDontKnow] yet.
How to do that ??? (actually contents from these two location are the contents of a html file and i want to store the contents of only html file present in this buffer). any ideas how to do that ??
You can use strnstr function to find the right position in your buffer. After you've found the starting and ending tag, you can extract the text inbetween using strncpy, or use it in place if the performance is an issue.
You can calculate needed size from the positions of the tags and the length of the first tag nLength = nPosEnd - nPosStart - nStartTagLength
Look for HTML parsers for C/C++.
Another way is to have a char pointer from the start of the buffer and then check each char there after. See if it follows your requirement.
If that's the only operation which operates on HTML code in your app, then you could use the solution I provided below (you can also test it online - here). However, if you are going to do some more complicated parsing, then I suggest using some external library.
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main()
{
const char* beforePrefix = "asdfasdfasdfasdf";
const char* prefix = "<!doctortype html";
const char* suffix = ".html>";
const char* postSuffix = "asdasdasd";
unsigned size = 1024;
char buf[size];
sprintf(buf, "%s%sTHE STRING YOU WANT TO GET%s%s", beforePrefix, prefix, suffix, postSuffix);
cout << "Before: " << buf << endl;
const char* firstOccurenceOfPrefixPtr = strstr(buf, prefix);
const char* firstOccurenceOfSuffixPtr = strstr(buf, suffix);
if (firstOccurenceOfPrefixPtr && firstOccurenceOfSuffixPtr)
{
unsigned textLen = (unsigned)(firstOccurenceOfSuffixPtr - firstOccurenceOfPrefixPtr - strlen(prefix));
char newBuf[size];
strncpy(newBuf, firstOccurenceOfPrefixPtr + strlen(prefix), textLen);
newBuf[textLen] = 0;
cout << "After: " << newBuf << endl;
}
return 0;
}
EDIT
I get it now :). You should use strstr to find the first occurence of the prefix then. I edited the code above, and updated the link.
Are you limited to C, or can you use C++?
In the C library reference there are plenty of useful ways of tokenising strings and comparing for matches (string.h):
http://www.cplusplus.com/reference/cstring/
Using C++ I would do the following (using buffer and size variables from your code):
// copy char array to std::string
std::string text(buffer, buffer + size);
// define what we're looking for
std::string begin_text("<!doctortype html");
std::string end_text(".html>");
// find the start and end of the text we need to extract
size_t begin_pos = text.find(begin_text) + begin_text.length();
size_t end_pos = text.find(end_text);
// create a substring from the positions
std::string extract = text.substr(begin_pos,end_pos);
// test that we got the extract
std::cout << extract << std::endl;
If you need C string compatibility you can use:
char* tmp = extract.c_str();