Using strstr in C MBED, printing result - c++

I'm trying to compare two char arrays and print to the terminal whether or not the string was found.
When I run my code, the output printed returns a load of jibber that's not related to what I specified. I think more memory than I've specified is being printed but I'm not sure why.
Strstr returns a pointer to the beginning index of the found string (if found), null if not. I'm guessing this is what is causing the error - but I thought by only checking if the result was null rather than printing the result would bypass this.
My code:
include "mbed.h"
include "string.h"
char input[] = "Hello mbed";
char value[] = "llo";
int main() {
char * output;
output = strstr(input, value);
bool found = false;
if (output != NULL) {
found = true;
}
printf(found ? "true" : "false");
}
My output:
trueloHello mbed½mà$Õ[F!FðMøDà(ÛÝéBÝ#\à0 ZFGñ##Ñ. ZFGmºñªñ
ÝÜàøZFGm¸ñ¨ñôÜ[F!F«æ-+ -éðAF%FFÔà9F °GmdùÕ(F½èð-éðAF%FFÈÕ0’à ‘ÕàAF8F°GmdùÕ(F½èðJh*Ð
hSpHh#HpGðµF°F2¡ü÷Èø(¿%0OÐWø%H±m-ùÓGà-IhB
`°ð½-?Ò x:(Ð!FhFþ÷ýhFþ÷mý(3ÐhFþ÷mý(hF Ðþ÷Uý#àjF¡ Fü÷Åøàþ÷?ý³ð¿$пð¿Dôtð¿DôdFhFþ÷UýF0h”Fh0FG(¿Gø%è°ð½Oðÿ0°ð½ð¿$ÛÑð¿ $$Õç:ttl :%p(¼¿ pGJëPø.......

here is a corrected code that cleanly compiles, and works as desired
Note the way the printf() parameters are being set
Note the corrected list of #include statements
//include "mbed.h"
#include <stdio.h> // printf()
#include <string.h> // strstr()
#include <stdbool.h> // bool, true, false
char input[] = "Hello mbed";
char value[] = "llo";
int main( void )
{
char * output = strstr(input, value);
bool found = false;
if (output)
{
found = true;
}
printf( "%s\n", ((found)? "true" : "false" ));
}

There's a problem with the compiler and how it works with const strings. Add the NULL character to the strings to see if it stops printing...
printf(found ? "true\0" : "false\0");

printf() might be a macro on your compiler/library/IDE. Including the header file, ensures that it works as expected. Also, on embedded, main() should never return

Related

Retrieve the name of the computer and saved it in a variable [duplicate]

This question already has answers here:
How do I properly compare strings in C?
(10 answers)
Closed 7 years ago.
I'm learning win32 programming with C/C++. In the process of learning, my teacher wanted I write a simple program that it can shows the name of the computer which It runs on it and Then, if the name of the target computer was "USER", shows a warning in the output console. I written the following code, but It doesn't work.
myFunction Code :
tchar * getComputerName() {
bufCharCount = INFO_BUFFER_SIZE;
if (!GetComputerName(infoBuf, &bufCharCount))
printError(TEXT("GetComputerName"));
return (TCHAR*)infoBuf;
}
calling code :
if (getComputerName() == (TCHAR*)"USER") {
printf("Target OS Detected \n");
}
how can i fix this issue?
There are several issues with the code as posted. The most blatant one is the use of TCHARs. TCHAR was invented, before Win9x had Unicode support, in an attempt to keep code source code compatible between Win9x and Windows NT (the latter uses Unicode with UTF-16LE throughout). Today, there is no reason to use TCHARs at all. Simply use wchar_t and the Windows API calls with a W suffix.
The C-style casts (e.g. return (TCHAR*)infoBuf) are another error waiting to happen. If the code doesn't compile without a cast in this case, this means, you are using incompatible types (char vs. wchar_t).
Plus, there's a logical error: When using C-style strings (represented through pointers to a sequence of zero-terminated characters), you cannot use operator== to compare the string contents. It will compare the pointers instead. The solution to this is to either invoke an explicit string comparison (strcmp), or use a C++ string instead. The latter overloads operator== to perform a case-sensitive string compare.
A fixed version might look like this:
#include <windows.h>
#include <string>
#include <iostream>
#include <stdexcept>
std::wstring getComputerName() {
wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1] = {0};
DWORD cchBufferSize = sizeof(buffer) / sizeof(buffer[0]);
if (!GetComputerNameW(buffer, &cchBufferSize))
throw std::runtime_error("GetComputerName() failed.");
return std::wstring(&buffer[0]);
}
int main() {
const std::wstring compName = getComputerName();
if ( compName == L"USER" ) {
std::wcout << L"Print your message" << std::endl;
}
}
The following code works for me:
#include <windows.h>
// ...
std::string get_computer_name()
{
const int buffer_size = MAX_COMPUTERNAME_LENGTH + 1;
char buffer[buffer_size];
DWORD lpnSize = buffer_size;
if (GetComputerNameA(buffer, &lpnSize) == FALSE)
throw std::runtime_error("Something went wrong.");
return std::string{ buffer };
}
You can't compare two string pointers to compare the string.
DWORD dw_computer_name = MAX_COMPUTERNAME_LENGTH;
TCHAR computer_name[MAX_COMPUTERNAME_LENGTH+1];
if ( 0 != GetComputerName( computer_name, &dw_computer_name ) )
{
printError( TEXT( "GetComputerName" ) );
if ( 0 == _tcscmp( computer_name, _T("HOST") )
{
printf( "Target OS Detected \n" );
}
}

Display an int variable in a MessageBox

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;
}

Getting system env in c++ from windows

I try to fetch some system env in windows from my C++ application. I tried getenv and GetEnvironmentVariable but both stuck. A program compiles but when I run it I see blinking pointer for some time, nothing displays and then program crash with message:
RUN FAILED (exit value -1 073 741 819, total time: 10s)
I tried a lot of examples from the net and all of them give the same result. Some examples I tried:
char l_strSingleVal[20];
GetEnvironmentVariable("PATH", l_strSingleVal,20);
printf("VariableName: %s\n",l_strSingleVal);
or:
std::string string_variable;
const std::string MY_VAR = "PATH";
char const* temp = std::getenv(MY_VAR.c_str());
if(temp != NULL)
{
string_variable = std::string(temp);
}
You have undefined behviour:
From GetEnvironmentVariable spec (l_strSingleVal is equivalent to lpBuffer): http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188(v=vs.85).aspx
If lpBuffer is not large enough to hold the data, the return value is
the buffer size, in characters, required to hold the string and its
terminating null character and the contents of lpBuffer are undefined.
Accessing lpBuffer in your case is UB. A 20 character buffer for PATH is way too small. You need to check the return value of GetEnvironmentVariable (which in your case will be telling you the size of the buffer required for successful invocation).
Tried C standard library function getenv? It works for me on my Windows PC.
Example:
#include <stdlib.h>
#include <stdio.h>
int main()
{
char * src = getenv("PATH");
if (src)
printf("value of PATH is: %s", src);
else
printf("empty or not defined");
return 0;
}

How to get unsigned int as console argument?

I'm trying to pass an unsigned int value via console argument to my program.
what have I tried yet:
first: check if argc is 2, otherwise error
if there is a second value I tried to convert this value with:
strtoul(argv[1], NULL, 0)
So when I pass "100", i get "1"
What am I doing wrong?
br
Sagi
€: passed a wrong argument to my function, found the mistake, thanks guys
It's a little hard to tell without seeing the actual code but you can use this as a baseline:
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char *pCh;
unsigned long unlong = 42;
// Check enough arguments.
if (argc != 2) {
puts ("Not enough arguments");
return 1;
}
// Convert to ulong WITH CHECKING!
unlong = strtoul (argv[1], &pCh, 10);
// Ensure argument was okay.
if ((pCh == argv[1]) || (*pCh != '\0')) {
puts ("Invalid number");
return 1;
}
// Output converted argument and exit.
printf ("Argument was %ld\n", unlong);
return 0;
}
Transcript follows:
pax> ./testprog 314159
Argument was 314159
If that's not enough to help out, I suggest you post the shortest complete program that exhibits the problem, then we can tell you in excruciating detail what's wrong with it :-)
Your method should work. Alternatively, you can use stringstream:
std::string str(argv[1]);
unsigned long ul;
std::stringstream(str)>>ul;

Passing a character array to function | Strange error

Basically I have a buffer in which i am looking for various flags to read certain fields from a binary file format. I have file read into a buffer but as i started to write code to search the buffer for the flags i immediately hit a wall. I am a C++ noob, but here is what i have:
void FileReader::parseBuffer(char * buffer, int length)
{
//start by looking for a vrsn
//Header seek around for a vrns followed by 32 bit size descriptor
//read 32 bits at a time
int cursor = 0;
char vrsn[4] = {'v','r','s','n'};
cursor = this->searchForMarker(cursor, length, vrsn, buffer);
}
int FileReader::searchForMarker(int startPos, int eof, char marker[], char * buffer)
{
int cursor = startPos;
while(cursor < eof) {
//read ahead 4 bytes from the cursor into a tmpbuffer
char tmpbuffer[4] = {buffer[cursor], buffer[cursor+1], buffer[cursor+2], buffer[cursor+3]};
if (strcmp(marker, tmpbuffer)) {
cout << "Found: " << tmpbuffer;
return cursor;
}
else {
cout << "Didn't Find Value: " << marker << " != " << tmpbuffer;
}
cursor = cursor + 4;
}
}
my header looks like this:
#ifndef __FILEREADER_H_INCLUDED__
#define __FILEREADER_H_INCLUDED__
#include <iostream>
#include <fstream>
#include <sys/stat.h>
class FileReader {
public:
FileReader();
~FileReader();
int open(char *);
int getcode();
private:
void parseBuffer(char *, int);
int searchForMarker(int, int, char[], char *);
char *buffer;
};
#endif
I would expect to get back a match for vrsn with strcmp but my result looks like this
Didn't Find Value: vrsn != vrsn
Found:
It looks like it finds it on the second pass after its passed the char array i am looking for.
Relevant hexcode
Your problem is two-fold:
strcmp returns "0" on success, not on failure. Read the documentation.
strcmp expects null-terminated strings. You say that you have chosen non-terminated char arrays because that's what your DB library uses. Well, fine. But still, you are violating the requirements of strcmp. Use strncmp instead (which takes a length argument) or, preferably, actually write C++ and start using std::vector<char> and friends.
Shouldn't that be something like int FileReader::searchForMarker(...) { .... }?
For the second query, I guess the strcmp works when it has two null terminated strings as its arguments. For example str1[]="AAA"; and str2[]="AAA"; then strcmp() would be used as
if(strcmp(str1,str2)==0) which will return 0 to indicate that they are equal. In your case, the tmpbuffer that you have created is not a null terminated string unless you add \0 in the end.So you might want to add \0 in the end of your tmpbuffer to create a string of 'v' 'r' 'n' 's'.
char vrsn[4] = {'v','r','s','n'};
Contains only the 4 characters specified. There is no room for a null character at the end.
char tmpbuffer[4] = {buffer[cursor], buffer[cursor+1], buffer[cursor+2], buffer[cursor+3]};
Contains only the 4 characters from buffer. There is no room for a null character at the end.
Eventually you call:
if (strcmp(marker, tmpbuffer)) {
The strcmp() function expects each of its parameters to end with a null character ('\0'). It wants to work with strings, which are null terminated.
Since your data is not null terminated, you probably want to use memcmp() instead of strcmp().
Also, strcmp() returns zero when its arguments are equal, so the condition in the if statement is inverted. (Zero is false, everything else is true.) The memcmp() function will also return zero when its arguments are equal.