Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

roomforthetuna posted:

I think also a member variable x in a superclass too if you want, though I'm not quite so sure about that one.

Yep. It's basically just "not twice in the exact same scope" with a few extra restrictions about variables declared in loop/if conditions (because they're almost the exact same scope).

Adbot
ADBOT LOVES YOU

shrughes
Oct 11, 2008

(call/cc call/cc)
Also, you should compile with warnings turned on. Maybe not every compiler has it but at least on some, warnings would have caught this.

PS. Love the cabin
Dec 30, 2011
Bee Lincoln
That's what I thought but the compiler didn't say anything and I'm anal about warnings.

Dren
Jan 5, 2001

Pillbug

PS. Love the cabin posted:

I had a dumb moment myself rearranging some code to have a local variable be global and wondering why later on it would all of the sudden be NULL.
As it turns out I forgot to remove the local declaration from one function so it was declared a second time and initialized to NULL.

Is that actually allowed or is it just a compiler bug?

http://en.wikipedia.org/wiki/Variable_shadowing

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
I have just started playing around with c++ creating a simple window and text box and have a few questions:

1) How do I set the window to redraw itself when resized, so it refills in the background colour as it is resized?
2) How do I get the textbox to be a decent size relative to the window? It keeps going off the bottom of the screen if not constrained vertically.
3)I have a few weird warnings that I would like to find out how to eliminate. Can you help me see where they come from?

BTW the password box was just practicing with EDIT styles and the background colour was just practicing changing the colour. This is just me dicking around as I learn.
Below are the code and build messages:

code:
#include <windows.h>
#include "resource.h"

const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;

    MSG Msg;
    HBRUSH hBrush;
    hBrush = CreateSolidBrush(RGB(0,24,56));
    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = hBrush;
    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);


    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    int width = 240;
    int height = 150;
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, width,height,
        NULL, NULL, hInstance, NULL);


    HINSTANCE entry;
    HWND textEntry = CreateWindow("EDIT",0,WS_BORDER|WS_CHILD|WS_VISIBLE|ES_PASSWORD,10,10,width*0.8,15,hwnd,0,entry,0);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    DeleteObject(hBrush);


    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

code:
||=== Build: Debug in WindowsPractice (compiler: GNU GCC Compiler) ===|
C:\Users\Chris\Documents\My Projects\C++\WindowsPractice\main.cpp||In function 'int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)':|
C:\Users\Chris\Documents\My Projects\C++\WindowsPractice\main.cpp|67|warning: unused variable 'textEntry' [-Wunused-variable]|
C:\Users\Chris\Documents\My Projects\C++\WindowsPractice\main.cpp|67|warning: 'entry' may be used uninitialized in this function [-Wuninitialized]|
||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|
||=== Run: Debug in WindowsPractice (compiler: GNU GCC Compiler) ===|
Also, if there are any best practice tips to improve the code's efficiency before I try anything more complicated let me know.

Thanks in advance

BioEnchanted fucked around with this message at 18:23 on Aug 13, 2014

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

eXXon posted:

I guess I may as well ask if it's true that there's a potentially meaningful performance difference between ++i and i++ in a for loop, if it's not optimized away at least.

I would think any C compiler written in the last 30 years will optimize i++ to ++i when it can (e.g., when the result is ignored).

Having said that, I have used at least one compiler that didn't, and to this day I prefer the prefix form. (Alcyon C on the Atari ST. Three passes plus assembler, with all intermediate files stored on (floppy!) disk. But it taught me so much... :corsair:)

The Gay Bean
Apr 19, 2004

giogadi posted:

This is actually a super interesting question but might be out of the scope of this thread. For what it's worth - I'm certain that fitting an affine transform to a dataset has been done before, but without doing any research, you might try a hybrid approach? I.e., use least squares to get an initial solution, then toss that initial solution into a local nonlinear optimizer like Levenberg-Marquardt (Ceres has this actually) where you use your constraint as your objective function.

This is fun to think about but my idea's probably horrible and this is definitely a derail so I'll stop here.

Research, it turns out, was actually the key to the solution. I have worked in MIT's incremental smoothing and mapping (ISAM) and it's working quite well in real-time for 6-DOF poses and 3-DOF landmarks.

VikingofRock
Aug 24, 2008




I have a C++ program which needs to call a series of command line tools that someone else has written, with arguments that could depend on user input. I know in python I would handle this by using the subprocess module with SHELL=False; what is the safe way to do this in C++(11)?

fritz
Jul 26, 2003

shrughes posted:

Also, you should compile with warnings turned on. Maybe not every compiler has it but at least on some, warnings would have caught this.

It looks like gcc doesn't warn about variable shadowing even with "-Wall -Wextra" (you need to explicitly specify "-Wshadow"), and clang needs "-Weverything".

But yeah, always run with warnings.

Dren
Jan 5, 2001

Pillbug

VikingofRock posted:

I have a C++ program which needs to call a series of command line tools that someone else has written, with arguments that could depend on user input. I know in python I would handle this by using the subprocess module with SHELL=False; what is the safe way to do this in C++(11)?

The language doesn't support it out of the box, it's platform dependent. What platform are you on?

VikingofRock
Aug 24, 2008




Dren posted:

The language doesn't support it out of the box, it's platform dependent. What platform are you on?

It needs to work for OSX and Linux.

nielsm
Jun 1, 2009



VikingofRock posted:

It needs to work for OSX and Linux.

Then it's probably straight execve() you want. It's a Unix standard system call, for executing a program with arguments given as an argv array.
Keep in mind that it replaces your current process with the new one, so you generally always want to fork() before exec'ing.

Since the arguments are passed as an array you generally won't run the risk of escaping-problems causing arguments to "leak" in unintended ways, but of course that can depend on the actual program called. You'll obviously also want to ensure that any filename arguments that might be based on user input can only reference files the user is actually allowed to operate on.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

VikingofRock posted:

I have a C++ program which needs to call a series of command line tools that someone else has written, with arguments that could depend on user input. I know in python I would handle this by using the subprocess module with SHELL=False; what is the safe way to do this in C++(11)?

You can define your own shell escaping function and use system(), or you can use fork() and exec*() as god intended.

execl* if you have a fixed number of arguments, or execv* if it can vary. exec*p if you want to look up the executable in PATH, exec*e if you need to set environment variables too.

VikingofRock
Aug 24, 2008




nielsm posted:

Then it's probably straight execve() you want. It's a Unix standard system call, for executing a program with arguments given as an argv array.
Keep in mind that it replaces your current process with the new one, so you generally always want to fork() before exec'ing.

Since the arguments are passed as an array you generally won't run the risk of escaping-problems causing arguments to "leak" in unintended ways, but of course that can depend on the actual program called. You'll obviously also want to ensure that any filename arguments that might be based on user input can only reference files the user is actually allowed to operate on.

Edison was a dick posted:

You can define your own shell escaping function and use system(), or you can use fork() and exec*() as god intended.

execl* if you have a fixed number of arguments, or execv* if it can vary. exec*p if you want to look up the executable in PATH, exec*e if you need to set environment variables too.


Okay cool, fork() -> execv() it is! Thanks so much!

Edit: Is there an easy way to get the output of the processes?

VikingofRock fucked around with this message at 21:35 on Aug 14, 2014

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

VikingofRock posted:

Okay cool, fork() -> execv() it is! Thanks so much!

Edit: Is there an easy way to get the output of the processes?

Nope, there's the difficult way that every other language abstracts over.
code:
int pipefd[2];
pipe(pipefd);
int pid = fork();
if (pid == 0){
    /* child */
    close(pipefd[0]);
    dup2(pipefd[1], STDOUT_FILENO);
    exec(...);
} else if (pid != -1) {
    /* parent */
    close(pipefd[1]);
    /* Use read pipefd[0], or wrap it with fdopen or some C++ thing */
}
There was a proposal to add an abstraction to the C++ standard library, but it doesn't look like it went anywhere.

Edison was a dick fucked around with this message at 22:23 on Aug 14, 2014

Dren
Jan 5, 2001

Pillbug

Edison was a dick posted:

Nope, there's the difficult way that every other language abstracts over.
code:
int pipefd[2];
pipe(pipefd);
int pid = fork();
if (pid == 0){
    /* child */
    close(pipefd[0]);
    dup2(pipefd[1], STDOUT_FILENO);
    exec(...);
} else if (pid != -1) {
    /* parent */
    close(pipefd[1]);
    /* Use read pipefd[0], or wrap it with fdopen or some C++ thing */
}

but what if the call to pipe fails :ohdear:

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

Dren posted:

but what if the call to pipe fails :ohdear:

Nothing at all muahahahahaa!

Oh, and apparently the pipeline proposal came with code:

http://code.google.com/p/google-concurrency-library/source/browse/include/pipeline.h

If you're doing bare C, http://libpipeline.nongnu.org/ may be worth looking at.

pseudorandom name
May 6, 2007

Ignore all this bad advice and just use popen().

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

pseudorandom name posted:

Ignore all this bad advice and just use popen().

Sure, if you want to have to escape your command, spawn a shell, have that unescape the command and then do what we just described.

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
I worked out how to neaten up my window and tried adding child windows (textbox and button) but the child button's event handler isn't working. LBUTTONDOWN is not being called when I click the button, however it works fine when moved to parent's event handler. Any help getting the button to click?
code:
#include <windows.h>
#include "resource.h"
#include <string>
#include <iostream>
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            // All painting occurs here, between BeginPaint and EndPaint.

            FillRect(hdc, &ps.rcPaint, (HBRUSH) (CreateSolidBrush(RGB(0,24,56))));

            EndPaint(hwnd, &ps);
        }

        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
using namespace std;
#define WM_MESSAGE (WM_USER+0)
LRESULT CALLBACK WndProcButton(HWND button,UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_LBUTTONDOWN:
        cout<<"click\n";
    break;

    default:
        return DefWindowProc(button,msg,wParam,lParam);
    }
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    HBRUSH hBrush;
    hBrush = CreateSolidBrush(RGB(0,24,56));
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = hBrush;
    wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MYMENU);
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);


    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    int width = 240;
    int height = 200;
    int margin = 10;
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW|WS_MAXIMIZE,
        CW_USEDEFAULT, CW_USEDEFAULT, width,height,
        NULL, NULL, hInstance, NULL);


    HINSTANCE entry;
    HINSTANCE button1;

    HWND textEntry = CreateWindow("EDIT",0,WS_BORDER|WS_CHILD|WS_VISIBLE|ES_PASSWORD,margin,10,width-margin*4,15,hwnd,0,entry,0);
    HWND button = CreateWindow("BUTTON","Push",WS_BORDER|WS_CHILD|WS_VISIBLE, margin, 30, 50, 25, hwnd,0,button1,0);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);
    DeleteObject(hBrush);


    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

nielsm
Jun 1, 2009



Your WndProcButton is not hooked up anywhere, and that isn't how you'd hook it up anyway, usually.
If you just want to handle the button being clicked normally by the user, you should handle WM_COMMAND in the containing window's wndproc, and check the wParam high word for which BN_* notification the button is sending (BN_CLICKED probably most interesting), and perhaps the wParam low word for control ID.

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
Thanks, that worked perfectly. I'll let you know if I have any more questions that I can't figure out on my own.

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
I am trying something different with a new window, trying to create a text box that I can change the size of. First of all though I get a warning when creating the textbox:

C:\Users\Chris\Documents\My Projects\C++\Making a Grid\Basic Window.c|11|warning: variable 'Resize_text' set but not used [-Wunused-but-set-variable]|
C:\Users\Chris\Documents\My Projects\C++\Making a Grid\Basic Window.c|14|warning: 'Resize' may be used uninitialized in this function [-Wuninitialized]|

Here is the code:
code:
#include <windows.h>
#include "definitions.h"
const char g_szClassName[] = "myWindowClass";

// Step 4: the Window Procedure

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        HWND Resize_text;
        HINSTANCE Resize;
        case WM_CREATE:
            Resize_text = CreateWindow("EDIT",0,WS_BORDER|WS_CHILD|WS_VISIBLE,10,10,50,50,hwnd,(HMENU)RESIZE_TEXT_BOX,Resize,0);
        break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    HBRUSH brush = CreateSolidBrush(RGB(0,0,255));

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = MainWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = brush;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);


    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW|WS_MAXIMIZE,
        CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
        NULL, NULL, hInstance, NULL);




    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);


    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

As you can see the variables do work and are initialised. How would I tie the initialisation statements to the createwindow function?

hamburger necktie
Jun 7, 2004

I'm watching

BioEnchanted posted:

C:\Users\Chris\Documents\My Projects\C++\Making a Grid\Basic Window.c|11|warning: variable 'Resize_text' set but not used [-Wunused-but-set-variable]|
You assign a value to Resize_text but then never use that variable again. This warning just means maybe you used the wrong variable later, and meant to use this one. I'm assuming that eventually, you will use this variable for something but just haven't gotten around to doing it yet (trying to get the current code to compile). If this is correct, you can ignore this warning.

BioEnchanted posted:

C:\Users\Chris\Documents\My Projects\C++\Making a Grid\Basic Window.c|14|warning: 'Resize' may be used uninitialized in this function [-Wuninitialized]|
You create the variable (but do not initialize it), and then pass it (still uninitialized) to the CreateWindow function. You should initialize the variable with a value before using it.

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
I figured out what the problem was. Moving the HINSTANCE declarations all the way out of the loop made them a global variable and it started seeing them from there.
EVENT HANDLING LOOP
{
DECLARE variable;
WM_CREATE
{
use variable;
}
}

results in "where is variable, it's not used and later there is a used version that isn't defined. I can't figure out this riddle::saddowns:"

DECLARE variable;

EVENT HANDLING LOOP
{
WM_CREATE
{
use variable;
}
}
results in "ohhhh, there it is!" :downs:

TheGame
Jul 4, 2005

:shepface:God I fucking love Diablo 3 gold, it even paid for this shitty title:shepface:
I'm a bit stumped on a part of a program for an intro to C class I'm taking. I'm supposed to make a program using structs that asks the user to enter basic data (address, phone number, name) on 10 different people/accounts. Afterwards, the program prompts the user to enter a state abbreviation (e.g. CO, OR) and returns a list of all accounts that are associated with that state.

I've got the first part down, but I can't figure out how I can compare the user-entered state code with the account-associated states since the == equality operator can't be used. No one in the class can figure out what to do and the professor's being very coy.

The part I can't figure out starts with 'char stateTemp[3].'

code:
#define _CRT_SECURE_NO_WARNINGS
#define SIZE 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
	char firstName[30];
	char lastName[30];
	char street[35];
	char city[20];
	char state[3];
	int zip;
	char phone[15];
	int accountId;
} Customer;

int main()
{
	Customer custDB[SIZE];
	int i;
	for (i = 0; i < SIZE; i++) // prompts user to enter data on 10 accounts
	{
		custDB[i].accountId = i + 1;
		printf("\nEnter Data for Customer %d", i + 1);
		printf("\nEnter First Last Phone: ");
		scanf("%s %s %s", custDB[i].firstName, custDB[i].lastName, custDB[i].phone);
		printf("\nEnter Address (Street City State ZIP): ");
		scanf("%s %s %s %d", custDB[i].street, custDB[i].city, custDB[i].state, &custDB[i].zip);
	}
	char stateTemp[3]; // HERE IS THE PART WHERE I AM DUMB
	printf("Enter a 2-character state code:"); // prompts user to select a state to assess
	scanf("%s", stateTemp);
	for (i = 0; i < SIZE; i++)
	{
		if (custDB[i].state == stateTemp) // prints accounts belonging to the selected state
		{
			printf("=============================================================\n");
			printf("\nData for Customer %d\n", custDB[i].accountId);
			printf("Account: %d\n", custDB[i].accountId);
			printf("Name: %s %s\n", custDB[i].firstName, custDB[i].lastName);
			printf("Addr: %s %s %s %d\n", custDB[i].street, custDB[i].city, custDB[i].state, custDB[i].zip);
			printf("Phone: %s\n", custDB[i].phone);
		}
	}
	system("pause");
}
I've googled around a lot and read that memcmp is a way to do it, but we haven't learned about that yet so I'm guessing there's a simpler solution I'm missing.

Praseodymi
Aug 26, 2010

string.h has a strcmp function I think. Pretty sure that's what you want.

You should really be using std::strings instead of chars, if that's allowed.

Edison was a dick
Apr 3, 2010

direct current :roboluv: only

TheGame posted:

code:
typedef struct {
	char firstName[30];
	char lastName[30];
	char street[35];
	char city[20];
	char state[3];
	int zip;
	char phone[15];
	int accountId;
} Customer;

	char stateTemp[3]; // HERE IS THE PART WHERE I AM DUMB



		if (custDB[i].state == stateTemp) // prints accounts belonging to the selected state

}
I've googled around a lot and read that memcmp is a way to do it, but we haven't learned about that yet so I'm guessing there's a simpler solution I'm missing.

memcmp and strcmp are the proper way to do this.

I suspect your professor may be suggesting you use a type punning trick though, since the value of the state code that actually matters is two characters, you can type-pun the code to a short int and compare those.

Your professor is a bad person if they are suggesting this, since it's much more clear to use memcmp and strcmp, since it shows the intent, they are portable, and if it's sane to implement it that way on your platform, will do the type punning for you.

A good reason not to do this yourself, is that it can cause portability issues. You could end up on a platform that doesn't allow unaligned accesses, so the type-punned comparison could end up comparing the wrong data.

You're not going to be bitten by it being ill-defined behaviour here, but it's a bad idea to do that in production software, and anyone who has to port it will hate you.

Praseodymi posted:

string.h has a strcmp function I think. Pretty sure that's what you want.

You should really be using std::strings instead of chars, if that's allowed.

Given he's doing an intro to C, rather than C++, no, he shouldn't.

Praseodymi
Aug 26, 2010

Edison was a dick posted:

Given he's doing an intro to C, rather than C++, no, he shouldn't.

Duh, that's what I get for trying to be clever. :v:

TheGame
Jul 4, 2005

:shepface:God I fucking love Diablo 3 gold, it even paid for this shitty title:shepface:
Thanks, strcmp works perfectly! The teacher's usually quite good, but she kind of prefers to let students figure stuff out on their own. As such she links to a ton of YouTube tutorials, I'm guessing I missed strcmp in one of those or something.

Dren
Jan 5, 2001

Pillbug
she might've wanted you to reason that strings are an array of characters so the only way to compare them is to compare the strings byte by byte, then write strcmp on your own

btw, strncmp is the one you want

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

Dren posted:

btw, strncmp is the one you want

Why?

Dren
Jan 5, 2001

Pillbug

hmm yeah i guess strcmp is fine

that scanf w/o a width specifier is no good though

C code:
#include <stdio.h>
#include <string.h>

int main()
{
    char state_code[3];
    char overrun[1024];
    memset(overrun, '\0', sizeof(overrun));
    printf("please enter 2 char state code: ");
    scanf("%s", state_code);

    printf("%s\n", overrun);

    return 0;
}
code:
$ ./a.out 
please enter 2 char state code: sasnioawiugiaewbuewcw
uewcw

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
He'll learn that later. Start with the basics first.

Dren
Jan 5, 2001

Pillbug
humm I forgot that -fstack-protector only triggers if you bust out of the function, it doesn't protect buffers

i.e. the code i posted w/ the overrun buffer runs just fine with -fstack-protector but this code

C code:
#include <stdio.h>
#include <string.h>

int main()
{
    char state_code[3];
    printf("please enter 2 char state code: ");
    scanf("%s", state_code);

    return 0;
}
blows up due to the stack canary
code:
$ ./a.out 
please enter 2 char state code: sasnioawiugiaewbuewcw
*** stack smashing detected ***: ./a.out terminated
Aborted (core dumped)

ExcessBLarg!
Sep 1, 2001
Doesn't it bother you at all that you're declaring character arrays (strings) that clearly have a finite size (two characters, plus the terminator), yet the program lets you enter strings much larger than that?

Thought much about what happens when you do enter a string longer than two characters?

Turns it "bad stuff happens". It's fine for toy programs that can blow up without any risks. But it's also one of the most common class of software vulnerabilities, responsible for a massive number of security issues and lost productivity.

Yeah, it's an early exercise in a beginning C course. But doing it in a kind-of right way isn't much more difficult. At least, the fundamental problem deserves some early mention so folks don't get too used to it.

TheGame
Jul 4, 2005

:shepface:God I fucking love Diablo 3 gold, it even paid for this shitty title:shepface:
I suppose I should've specified that the class in question is for non-CS majors and is a quarter long, so I've been learning C for a little under 2 months and probably won't continue past here. As such most assignments say something to the effect of "You can assume that the user always enters proper data - no input validation is required."

The text has discussed overflow, but terms like 'stack canary' and 'core dumped' and ideas like 'reasoning that strcmp is probably a thing because arrays need to be compared byte by byte' are kind of beyond the scope of the class when structures were learned literally 3 days ago. It's not that I don't appreciate the help (I do), or that I don't understand the importance of clean or proper coding, I'm just trying to explain why the assignment text is the way it is.

shrughes
Oct 11, 2008

(call/cc call/cc)

ExcessBLarg! posted:

Doesn't it bother you at all that you're declaring character arrays (strings) that clearly have a finite size (two characters, plus the terminator), yet the program lets you enter strings much larger than that?

Thought much about what happens when you do enter a string longer than two characters?

Turns it "bad stuff happens". It's fine for toy programs that can blow up without any risks. But it's also one of the most common class of software vulnerabilities, responsible for a massive number of security issues and lost productivity.

strcmp is not overwriting any memory.

shrughes fucked around with this message at 05:43 on Aug 18, 2014

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

TheGame posted:

The text has discussed overflow, but terms like 'stack canary' and 'core dumped' and ideas like 'reasoning that strcmp is probably a thing because arrays need to be compared byte by byte' are kind of beyond the scope of the class when structures were learned literally 3 days ago. It's not that I don't appreciate the help (I do), or that I don't understand the importance of clean or proper coding, I'm just trying to explain why the assignment text is the way it is.

Just ignore Dren. It's obvious given the assignment that you weren't expected to care about these things yet.

Adbot
ADBOT LOVES YOU

BioEnchanted
Aug 9, 2011

He plays for the dreamers that forgot how to dream, and the lovers that forgot how to love.
I'm trying to compare cursor position to rect position so that the screen sees when the mouse overlaps with a child window, but the rect coordinates are so large comparison is worthless. The mouse pos is fine, coming up as (245,302) but no matter what I do the rect.left and rect.right come up as numbers like 45677754, so figuring out whether the mouse in inbetween them is impossible. Is there a function that I'm missing or a way to reconcile this?

Also, how can I set childWin to be either of the text boxes?

code:
#include <windows.h>
#include "definitions.h"
#include <string>
#include <iostream>
#include <windowsx.h>
const char g_szClassName[] = "myWindowClass";
using namespace std;
class text_box_resize{LPCTSTR type, default_text; DWORD style,style1,style2; int loc_x, loc_y, size_x, size_y; HWND parent;HMENU menu;HINSTANCE instance;LPVOID lParam;int unique_id;
                    public: void create(LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,int,int,int,int,HWND,HMENU,HINSTANCE,LPVOID);
                    void cursorpos();
};
void text_box_resize::create(LPCTSTR t,LPCTSTR def ,DWORD st1,DWORD st2,DWORD st3,int x,int y,int x1,int y1, HWND par,HMENU men,HINSTANCE inst,LPVOID other){
HINSTANCE inst1 = inst;
CreateWindow(t,def,st1|st2|st3,x,y,x1,y1, par, men, inst1 ,other);
};
void text_box_resize::cursorpos(){
cout<<"hovering";

};
// Step 4: the Window Procedure

HINSTANCE edit, edit2, edit3;
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch(msg)
    {
        case WM_CREATE:
            text_box_resize text_box;
            text_box.create("EDIT",0,WS_BORDER,WS_VISIBLE,WS_CHILD,10,10,50,50,hwnd,(HMENU)RESIZE_TEXT_BOX,edit,0);
            text_box.create("EDIT",0,WS_BORDER,WS_VISIBLE,WS_CHILD,70,10,50,50,hwnd,(HMENU)RESIZE_TEXT_BOX,edit2,0);
        break;
        case WM_DESTROY:

            PostQuitMessage(0);
        break;
        case WM_MOUSEMOVE:
            HWND childWin;
            POINT mouse_pos;
            childWin = FindWindow("EDIT",NULL);
            RECT txtPt;
            GetCursorPos(&mouse_pos);
            ScreenToClient(childWin,&mouse_pos);
            GetClientRect(childWin,&txtPt);
            ClipCursor(&txtPt);

            cout<<"("<<mouse_pos.x<<","<<txtPt.left<<","<<txtPt.right<<")";
            MapWindowPoints(hwnd,childWin,(LPPOINT)&txtPt,2);

        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
    HBRUSH brush = CreateSolidBrush(RGB(0,0,255));

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = MainWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = brush;
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);


    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        "The title of my window",
        WS_OVERLAPPEDWINDOW|WS_MAXIMIZE,
        CW_USEDEFAULT, CW_USEDEFAULT, 500,500,
        NULL, NULL, hInstance, NULL);




    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);


    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}


EDIT TO CLARIFY: Experimenting with rects I found that the (rect.left,rect.right) for the parent window are 0,480 but for the child window are (2686136,1964993873) Why is the child window so much bigger than the main window? The child should be pointing to the textboxes and the parent to the main window.

BioEnchanted fucked around with this message at 09:57 on Aug 18, 2014

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply