C++ string.substr compiles differently - x11

I have two pairs of files. The source files are identical copies apart from the path to the identical text files they interrogate.
One pair runs on Linux Cinnamon 18.x the other on Raspbian Stretch. Each pair is compiled on its own platform.
std::string sTemp = ImportDS18B20("testy.txt");
if (sTemp.find("YES") != std::string::npos) {
size_t p = sTemp.find("t= ");
if (p != std::string::npos) {
p += 3;
sFloor = sTemp.substr(p);
uint uTemp = sFloor.length();
std::cout << uTemp << " |" << sFloor << "| " << std::endl;
}
break;
}
The code produces 5 |19555| on Raspbian and 6 |19555\n| on Cinnamon. (\n is of course just to represent a CR on this site.)
I assume this is a C++ compiler issue. Is that correct? How do I make the code portable?

I suspect that your issue is with the ImportDS18B20() function rather than the code you've posted or the compiler. To verify that the files are identical, check the length and md5sum.
I would strip trailing \r (and \n to make it cross-platform)
sFloor = sTemp.substr(p);
while (sTemp.back() == '\r' || sTemp.back() == '\n')
sTemp.pop_back();
uint uTemp = sFloor.length();
Mike

Related

Output won't format correctly. Creates Random Indents

I am new to C++ and programming.
I am using the CLion editor. I created a simple program for a homework assignment and I can't figure out why my out put indents every line after the second line. I have searched online and here, but most indent questions ask how to indent, not how to make your output stop indenting when I never asked it to.
Thanks in advance for any help. I appreciate it.
I tried using code to left align, but that didn't work. I also tried creating a new project and retyping it in. I still got the same result.
I also tried adding a new line break--that prevents the indent, but then I have a blank line.
I think it may be a setting---but I have no idea which setting to change.
`
#include <iostream>
#include<iomanip>
using namespace std;
int main()
{
int numberPennies, numberNickels, numberDimes, numberQuarters,
totalCents;
cout << "Please Enter Number of Coins: " << endl;
cout << "# of Quarters: ";
cin >> numberQuarters;
cout << "# of Dimes: ";
cin >> numberDimes;
cout << "# of Nickels: ";
cin >> numberNickels;
cout << "# of Pennies: ";
cin >> numberPennies;
totalCents = int((numberQuarters * 25) + (numberDimes * 10) +
(numberNickels * 5) + (numberPennies));
cout << "The total is " << int(totalCents / 100) << " dollars and "
<< int(totalCents % 100) << " cents ";
return 0;}`
The result should be left aligned, instead my output appears like this:
`Please Enter Number of Coins:
# of Quarters:13
# of Dimes:4
# of Nickels:11
# of Pennies:17
The total is 4 dollars and 37 cents
Process finished with exit code 0`
It seems like you're doing everything right, I ran this code in Visual Studio 2019 and didn't have the issue you're describing. I think that the indentation you're seeing might be a feature of your IDE.
Try running the .exe you're generating instead of using the built in console in your IDE.

How to get source location of #includes using clang libtooling?

Is there any way to get clang::SourceLocation for every #include in file by its clang::FileID or clang::FileEntry or something?
What about using source manager's GetIncludedLoc function which takes fileid as parameter.
SourceManager.GetIncludedLoc(fileid)
Thank's #Hemant for your answer, you're right
I Already found that by myself (in clang 3.8 it is called getIncludeLoc)
but forgot to write here.
I used this to find the location after all #includes where i can put my own.
Here's the function (For sure not the best way) I wrote for this, hope it helps someone
SourceLocation getIncludeLocation(FileID fileID, SourceManager &sm, unsigned carriages) {
return SourceLocation();
set<unsigned> lines;
if (fileID.isInvalid())
for (auto it = sm.fileinfo_begin(); it != sm.fileinfo_end(); it++) {
SourceLocation includeLoc = sm.getIncludeLoc(sm.translateFile(it->first));
if (includeLoc.isValid() && sm.isInFileID(includeLoc, fileID)) {
lines.insert(sm.getSpellingLineNumber(includeLoc));
}
}
unsigned pos(0);
if (!lines.empty()) {
bool first = true;
for (unsigned line :lines) {
if (first)
first = false;
else if ((line - pos) > carriages)
break;
pos = line;
//cout << "Include line:" << pos << endl;
}
//cout << console_hline('-') << endl;
}
cout << sm.getFileEntryForID(fileID)->getName() << endl;
return sm.translateFileLineCol(sm.getFileEntryForID(fileID), ++pos, 1);
}
Also some information about includes can be get by
Preprocessor::GetIncludeFilenameSpelling(SourceLocation Loc, StringRef &Buffer)
and
Lexer::ComputePreamble(StringRef Buffer, const LangOptions &LangOpts, unsigned MaxLines = 0)

Reading Data from a Physical Hard Drive

I am trying to develop a program that goes and finds 2 connected unformatted physical drives and read bytes. The program currently runs in the administrator mode since that's the only way I guess the program can see unformatted hard drives. I am using visual studio 2015 and it runs in windows 7 machine.
The problem is that it can only read multiples of 512 (512 is the sector size). Currently the unformatted hard drives are located in disk 2 and 3 slots (they are both SSDs). It first reads 512 bytes (works without an issue) and doesn't do any more reads if it's a formatted hard drive. If it's an unformatted hard drive it goes ahead and read more bytes. If it's hard drive A it then reads the next 1024 bytes and it works (read_amount = 1024). If it's hard drive B it then reads the next 1025 bytes and it doesn't work (read_amount = 0). I am not sure why it can't read a multiple of a 512/sector sizes. My understanding is that when you call "CreateFile()" function with dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, I should be able to read sizes that are not multiples of sector sizes (if you use FILE_FLAG_NO_BUFFERING then you can only read multiples of 512 and I am NOT using that flag). See my code below.
// Hard_Drive_Read.cpp : Defines the entry point for the console application.
// This program assumes you have EXACTLY TWO unformatted hard drives connected to your computer.
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
if (argc != 3)
{
cout << "Need to enter 2 arguments" << endl;
exit(0);
}
int frames_to_process = atoi(argv[2]);
if (frames_to_process < 1)
{
cout << "invalid argument 2" << endl;
exit(0);
}
//HANDLE hDisk_A;
//HANDLE hDisk_B;
LPCTSTR dsksrc = L"\\\\.\\PhysicalDrive";
wchar_t dsk[512] = L"";
bool channel_A_found = false;
bool channel_B_found = false;
char frame_header_A[1024];
char frame_header_B[1025];
HANDLE hDisk;
char buff_read[512];
DWORD read_amount = 0;
for (int i = 0; i < 4; i++)
{
swprintf(dsk, 511, L"%s%d", dsksrc, i);
hDisk = CreateFile(dsk, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDisk == INVALID_HANDLE_VALUE)
{
printf("%s%d%s", "couldn't open the drive ", i, "\n");
CloseHandle(hDisk);
}
else
{
printf("%s%d%s", "successfully open the drive ", i, "\n");
BOOL read_success_1 = ReadFile(hDisk, buff_read, 512, &read_amount, NULL);
cout << "read amount 1 - " << read_amount << endl;
if ((read_success_1 == TRUE) && (read_amount == 512))
{
if ((buff_read[510] == (char)0x55) && (buff_read[511] == (char)0xAA)) // test for a formatted drive; is there other identifiers?
{
cout << i << " is a formatted drive" << endl;
}
else
{
cout << "Not a formatted drive, trying to find sync " << endl;
ofstream writeBinary_Test;
if (i == 2)
{
writeBinary_Test.open("file_A_test.bin", ofstream::out | ofstream::binary);
ReadFile(hDisk, frame_header_A, 1024, &read_amount, NULL);
cout << "read amount " << read_amount << endl;
writeBinary_Test.write(frame_header_A, 1024);
writeBinary_Test.close();
}
else if(i == 3)
{
writeBinary_Test.open("file_B_test.bin", ofstream::out | ofstream::binary);
ReadFile(hDisk, frame_header_B, 1025, &read_amount, NULL);
cout << "read amount " << read_amount << endl;
writeBinary_Test.write(frame_header_B, 1025);
writeBinary_Test.close();
}
LARGE_INTEGER distanceToMove;
SetFilePointerEx(hDisk, distanceToMove, NULL, FILE_BEGIN);
}
}
else
{
}
}
if (channel_A_found && channel_B_found)
{
cout << "both drives found" << endl;
break;
}
}
if ((channel_A_found == false) || (channel_B_found == false))
{
cout << "Couldn't Find Hard Drive A or Drive B or Both" << endl;
cout << "Exiting the program" << endl;
exit(0);
}
CloseHandle(hDisk);
return 0;
}
Eventually, I want to use SetFilePointerEx() to move around the hard drive and I the program has to work with and data size (not multiples of 512). Therefore, it's imperative I can read sizes that's not multiples of 512. Any ideas of how to fix this program? Am I using my flags properly?
Any help is much appreciated!
The documentation for CreateFile says:
Volume handles can be opened as noncached at the discretion of the particular file system, even when the noncached option is not specified in CreateFile. You should assume that all Microsoft file systems open volume handles as noncached. The restrictions on noncached I/O for files also apply to volumes.
Although it doesn't spell it out explicitly, this applies to drives as well as to volumes.
In practice, this isn't a problem. It is straightforward to write a helper function that returns an arbitrary amount of data from an arbitrary offset, while performing only aligned reads.
It's imperative I can read sizes that's not multiples of 512.
That is not possible. For direct access of a disk, you can only read and write multiples of the sector size. Furthermore, you must align your read and write operations. That is the file pointer must be at a multiple of the sector size.
If you want to present an interface that allows arbitrary seeking, reading and writing, then you will need to implement your own buffering on top of the aligned raw disk access.

std::cout seems to be printing out an extra "|" when called initially

I am working on a portion of my code that is suppose to output the error message correctly.
Please see below screenshot, I am using on bash
./myProgram < input3a.in | diff -a -y output3a.out -
Left hand side is what I want to get to.
For some reason an extra "|" is printed before the char array 'line' is printed. I suspected that maybe the char array 'line' is not null terminated. but it is initialize by cin.getline(); which should null terminate the char array.
Here i try to print the 'line' array in my main procedure, and it left the | sign on the line before it.
my question is. why does std::cout display this behaviour?
Thanks
EDIT,
Below is my code in question. Thanks for taking a look again.
#include "char_stack.h"
#include <iostream>
void printErrorLine(int errorSpot, int c_count, char line[]){
//Print the first line of error message char by char, at the
//same time replace char with \t or space
for(int x = 0; x <= errorSpot; x++){
std::cout << line[x];
if(line[x] != '\t'){
line[x] = ' ';
}
}
std::cout << std::endl;
//Print out the second line, if the first line does not have a
//errorSpot, then dont print it
if(errorSpot != c_count){
std::cout << line << std::endl;
}
}
char findCounterPart(char bracket){
//pass.
}
int main(int argc, char * argv[]){
char line[250]; // 250 because spec sheet detailed max 250 char per line.
char c;
int l_count = 0; // number of lines already read
int c_count; // character count in a line
char_stack S;
bool isError;
while(!std::cin.peek() == std::cin.eof()){
std::cin.getline(line, 250);
c_count = std::cin.gcount();
l_count +=1;
//std::cout<< c_count << std::endl << std::endl;
//loop through the line
for(int x = 0; x < c_count; x++){
c = line[x];
//std::cout << c << " stack size is " << S.size() << std::endl;
if (c == '(' ||
c == '{' ||
c == '['){
S.push(c);
}
else if(c == ')' ||
c == '}' ||
c == ']'){
if(S.empty()){
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
isError = true;
}
else{
char l = S.pop();
if(l != findCounterPart(c)){
std::cout << "Error on line " << l_count << ": Read " << c <<
", expected " << findCounterPart(l) << std::endl;
isError = true;
}
}
}
if (isError){
printErrorLine(x, c_count ,line);
return 0;
}
}
}
if (!S.empty()){
c = S.pop();
std::cout << "Error on line " << l_count << ": Too many " << c << std::endl;
printErrorLine(c_count, c_count , line);
}
else{
std::cout <<"No Errors Found" << std::endl;
}
return 0;
}
Learning to be a software engineer is about breaking problems down into manageable chunks, and here we have a couple of doosies. Lets rephrase your question slightly:
I am getting unexpected characters displayed when diff the output of my program against a file containing output of a previous run. Currently I think this is because of some weird behavior of std::cout.
Well, that might be a reasonable assumption, we can't see your code so we can't know if you're doing anything peculiar.
But it would have to be: std::cout is used, well, all over the place. It just doesn't have this behavior unless your code is deliberately writing a | somewhere.
There are a number of steps we could take to resolve this:
Run the program a 3rd time in the debugger and step through until you have some ideas where the '|' is appearing,
Run the program a 3rd time to the console and observe the output,
View the output using a command like cat, less or more, instead of diff
3 is perhaps the most sensible place to start, since the file is already right there and after that #2 will give us a mk1eyeball check.
What we find is: the | does not appear in the file or the output. It's not coming from your program.
Lets create a couple of .txt files and diff them:
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nSecond line' >test1.txt
osmith#WOTSIT MINGW64 ~
$ echo -e 'First line\nFile two line 2' >test2.txt
osmith#WOTSIT MINGW64 ~
$ diff -a -y test1.txt test2.txt
First line First line
Second line | File two line 2
When using the -y switch, between the two columns of output, diff has a line of special characters to indicate lines that changed, were inserted or deleted.

how to get char* filename from boost path

for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
{
if (iter->path().extension() == ".png"){
fs::path currentPath = iter->path();
const char *filename = const_cast<char*>(currentPath.string().c_str());
std::cout << iter->path().leaf() << std::endl;
processFile(filename);
std::cout <<"Hi" << std::endl;
}
}
This is my code and here processFile functions accepts the filename in char* format. Above code returns a junk value of filename. Don't know what is the best way to get the filename.
It works fine for me here (Boost.1.52, Mac OS X, clang).
Though I have to agree with Miguel, you're doing way to much work here.
for (fs::directory_iterator iter(realPath); iter != end_iter; ++iter )
if (iter->path().extension() == ".png") {
fs::path currentPath = iter->path();
std::cout << currentPath.leaf() << std::endl;
processFile(currentPath.c_str ());
}
and depending on your taste in code, you could get rid of currentPath altogether ( replace it with iter->path() )

Resources