Comparison of unsigned int is always true (npos issue?) - c++

I’m receiving an error:
error: comparison of constant 18446744073709551614 with
expression of type 'unsigned int' is always true
[-Werror,-Wtautological-constant-out-of-range-compare]
The line of code it is referring to is this:
if (key_index != std::string::npos)
key_index is an unsigned int local variable in my main() function that my if statement is also in.
I read through a few posts on here already, trying to make sense of where I’m going wrong.
This link was the most informative
What does string::npos mean
But, even utilizing the advice from there, I’m still coming up with the same errors.
I’ve tried to create my own variable:
const int NPOS = -1
I’ve modified the comparison operator a few different ways.
I’ve tried turning the line into:
if(key_index != (std::string::npos -1))
I’ve tried a few other minor changes, which I cannot recall at the moment.
I forgot to write them down, and I apologize for not having all of my test/mod details.
This is the full main() code the issue is coming from. For all I know, there might be something else that I need to correct instead.
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Window.hpp>
#include <math.h> // For pow()
#include <string>
#include <stdexcept> // For std::runtime_error
#include <vector>
#include "GuitarString.hpp"
const sf::Uint32 quit_key = 27; // ASCII 27 is the Escape key
const std::string keyboard = "q2we4r5ty7u8i9op-[=zxdcfvgbnjmk,.;/' ";
const int num_keys = keyboard.length();
const int kDuration = 8;
std::vector<sf::Int16> makeSamplesFromString(GuitarString *gs) {
std::vector<sf::Int16> samples;
gs->pluck();
for (int i= 0; i < kSampleRate * kDuration; i++) {
gs->tic();
samples.push_back(gs->sample());
}
return samples;
}
int main() {
sf::Event event;
double frequency;
unsigned int key_index;
std::vector < std::vector<sf::Int16> > samples(num_keys);
std::vector<sf::SoundBuffer> buffers(num_keys);
std::vector<sf::Sound> sounds(num_keys);
for (int i = 0; i < num_keys; ++i) {
frequency = 440 * pow(2, (i-24) / 12.0L);
GuitarString gs = GuitarString(frequency);
samples[i] = makeSamplesFromString(&gs);
if (!buffers[i].loadFromSamples(&samples[i][0],
samples[i].size(), 2, kSampleRate)) {
throw std::runtime_error("sf::SoundBuffer: failed to load from samples.");
}
sounds[i].setBuffer(buffers[i]);
}
sf::Vector2u size_win(500, 200);
sf::Sprite background_sprite;
sf::Texture background_texture;
if (background_texture.loadFromFile("keyboard.png")) {
background_sprite.setTexture(background_texture);
size_win = background_texture.getSize();
}
sf::RenderWindow window(sf::VideoMode(size_win.x, size_win.y),
" PS5B GuitarHero - Press Escape to Exit ");
window.setKeyRepeatEnabled(false);
while (window.isOpen()) {
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::TextEntered:
key_index = keyboard.find(event.text.unicode);
if (key_index != std::string::npos) { // the line causing the issue….
sounds[key_index].play();
} else if (event.text.unicode == quit_key) {
window.close();
}
break;
default:
break;
}
window.clear(sf::Color::Black);
window.draw(background_sprite);
window.display();
}
}
return 0;
}

If you're on a 64bit system, std::string::npos is almost certainly a 64bit number. To ensure maximum portability, use the type specified by std::string.
std::string::size_type key_index;
That should work, regardless of whether you're on a 32 or 64 bit system.

Related

OS X - Keypress in an if statement

I am quite new to C++ programming and using Mac as a computer.
I've been searching around the internet for a while now but I can't still find a good solution for my problem.
I am making a project with the Keyboard Arrows, but I don't know how to make the Keypress function in an if statement.
So the solution I am searching for is:
if (up arrow is pressed) {
std::cout << it worked! << std::endl;
}
Information:
LLVM Compiler, Xcodes command line tool, Unix, OS X-Sierra
Thank you for the help.
Well I couldn't get the code in the other answer to work, not sure what's different since I'm also running Sierra. But I converted it to using tcsetattr. The point of that call is to put the terminal in raw mode, such that it sends key presses directly. If you don't do that it won't send anything until you press enter.
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
static struct termios savemodes;
static int havemodes = 0;
int tty_break(void)
{
struct termios modmodes;
if (tcgetattr(STDIN_FILENO, &savemodes) < 0)
return -1;
havemodes = 1;
modmodes = savemodes;
cfmakeraw(&modmodes);
return tcsetattr(STDIN_FILENO, TCSANOW, &modmodes);
}
int tty_getchar(void)
{
return getchar();
}
int tty_fix(void)
{
if(!havemodes)
return 0;
return tcsetattr(STDIN_FILENO, TCSANOW, &savemodes);
}
int
main(int argc, char *argv[])
{
int i;
if(tty_break() != 0)
return 1;
for(i = 0; i < 10; i++)
printf(" = %d\n", tty_getchar());
tty_fix();
return 0;
}
I have put the code which I linked to in the comments together into a single program so you can see how it works.
#include <stdio.h>
#include <sgtty.h>
static struct sgttyb savemodes;
static int havemodes = 0;
int tty_break()
{
struct sgttyb modmodes;
if(ioctl(fileno(stdin), TIOCGETP, &savemodes) < 0)
return -1;
havemodes = 1;
modmodes = savemodes;
modmodes.sg_flags |= CBREAK;
return ioctl(fileno(stdin), TIOCSETN, &modmodes);
}
int tty_getchar()
{
return getchar();
}
int tty_fix()
{
if(!havemodes)
return 0;
return ioctl(fileno(stdin), TIOCSETN, &savemodes);
}
main()
{
int i;
if(tty_break() != 0)
return 1;
for(i = 0; i < 10; i++)
printf(" = %d\n", tty_getchar());
tty_fix();
return 0;
}
You can compile it simply with:
clang main.c -o main
and run it with:
./main
You will see that the ↑ (Up Arrow) key causes the following codes:
27 (Escape)
91
65
Note the code is not mine - it is entirely extracted from the C-FAQ I mentioned above.

C++ ASCII game console screen flickering

I am making a simple game using C++
It's just a tile game with an ASCII map.
The game itself works fine, but the console screen(map) is flickering when I move my player and I don't know how to fix this. Any help appreaciated, thanks!
Code:
#include <iostream>
#include <windows.h>
#include <conio.h>
#include <ctime>
#include <vector>
#include <string>
#include <cstdlib>
#include <fstream>
using namespace std;
vector<string> map;
int playerX = 10;
int playerY = 10;
int oldPlayerX;
int oldPlayerY;
bool done = false;
void loadMap();
void printMap();
void setPosition(int y, int x);
void eventHandling();
int main()
{
loadMap();
map[playerY][playerX] = '#';
printMap();
while(!done){
eventHandling();
printMap();
}
exit(1);
return 0;
}
void eventHandling(){
char command;
command = _getch();
system("cls");
oldPlayerX = playerX;
oldPlayerY = playerY;
if(command == 'w'){
playerY--;
}else if(command == 'a'){
playerX--;
}else if(command == 'd'){
playerX++;
}else if(command == 's'){
playerY++;
}
if(map[playerY][playerX] == '#'){
playerX = oldPlayerX;
playerY = oldPlayerY;
}
setPosition(playerY,playerX);
}
void setPosition(int y, int x){
map[oldPlayerY][oldPlayerX] = '.';
map[y][x] = '#';
}
void printMap(){
for(int i = 0 ; i < map.size() ; i++){
cout << map[i] << endl;
}
}
void loadMap(){
ifstream file;
file.open("level.txt");
string line;
while(getline(file, line)){
map.push_back(line);
}
}
std::cout is not intended to be used that way.
You should refer to the system specific API for the target OS and environment. For example, for Windows you should use Console API functions for your purpose. These functions are defined in Wincon.h include file.
It also helps if you use a double buffering system such that only what needs to be overwritten every frame is changed. IO operations are extremely expensive so ought to be minimized.
Cameron Gives a Very Thorough Description of How to Do this Here
But in essence, you'd use two arrays, one containing the current state of the map, one containing the previous state and only write to the specific locations that have changed.
One method to clear the screen that works on many systems is to print the form feed character, \f. The Linux console supports this, and so did MS-DOS if you loaded ansi.sys. Unix has ncurses and terminfo to abstract these functions.

Segmentation fault, array hell?

there seemed to be a lot of people with the segmentation fault problem but I couldn't seem to find any that related to my program, if there is a thread I'm sorry, I looked through multiple though and couldn't find it.
pretty much everything so far:
#include <SDL.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <time.h>
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int maxLandMass = SCREEN_WIDTH * SCREEN_HEIGHT;
const int landPercentage = 30;
const int maxHeight = 200;
const int numAnts = 10;
int main(int argc, char **argv)
{
int currentLandMass = 0;
int ants[numAnts][3]={{0}}; //x,y,pDir (0123,NESW)
std::string rules[numAnts]={0};
std::string rule;
int states = 2;
std::cout << "Which rule would you like to use? ";
std::cin >> rule;
if(rule == "")
{
rule = "RL";
}
else if(rule == "RND" || rule == "rnd")
{
std::cout << "How many states? ";
std::cin >> states;
}
srand(time(NULL));
for(int i = 0;i < numAnts;i++)
{
ants[i][0] = rand() % SCREEN_WIDTH;
ants[i][1] = rand() % SCREEN_HEIGHT;
ants[i][2] = rand() % 4;
if(rule != "RND" && rule != "rnd")
{
rules[i] = rule;
}
else
{
std::string tempRule;
for(int s = 0; s < states; s++)
{
int r = rand() % 2;
if(r == 0){ tempRule += "L"; }
if(r == 1){ tempRule += "R"; }
}
rules[i] = tempRule;
}
std::cout << rules[i] << "\n";
}
SDL_Window* window = NULL;
SDL_Surface* surface = NULL;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
}
else
{
window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if( window == NULL )
{
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
}
else
{
surface = SDL_GetWindowSurface(window);
SDL_FillRect(surface, NULL, SDL_MapRGB(surface->format, 0x00, 0x00, 0x00));
SDL_UpdateWindowSurface(window);
}
}
//Uint16 *pixels = (Uint16 *) surface->pixels;
/////////////////////////////
int grid[SCREEN_HEIGHT][SCREEN_WIDTH]={{0}};
int heights[SCREEN_HEIGHT][SCREEN_WIDTH]={{0}};
int prevState = 0;
for(int a = 0; a < numAnts; a++)
{
//TODO add stuff here
}
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
When it runs it should start with a console window to get some input from the user then switch to an SDL window and do its thing, but the console window tells me:
terminate called after throwing an instance of 'std::logic_error'
what():basic_string::_S_construct null not valid
I have a feeling its something to do with how I have initialised (or at least tried to) the arrays.
The part that I added last was the bit below the ////// line I made.
let me know if you will need more info, Ill get it as soon as I can, and I apologise for my programs current state, its messiness is driving me a bit mad too but (until I broke it) it worked :P
You are initializing your array of strings with zeros. That's an invalid initialization.
Interestingly, had you picked any other number, you'd get a clearer error message, telling you that you're doing an invalid conversion from int to const char* (which is a c-style string, and the closest valid input type std::string has a constructor for).
Unfortunately, the zero initialization is confusing your compiler to think you're actually assigning a pointer, which it may convert, but luckily it checks and sees that the pointer is NULL, and therefore bails out with the error message you saw: basic_string::_S_construct null not valid.
I took your code and removed all the SDL part, it compiled and reproduced the error.
I then replaced
std::string rules[numAnts]={0};
with
std::string rules[numAnts];
which uses the default constructor to create empty strings for all elements, and now it seems to work.

Web Browser Turbo C++

So I was browsing the Internet for a project and stumbled upon this piece of code. It runs perfectly until the point you enter a website(include "www" :P) and press Enter and then boom! The program terminates, no error message, nothing.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <dos.h>
#include <string.h>
void initialize_graphics_mode();
int get_key();
void draw();
union REGS i, o;
main()
{
int key, i = 0, xpos, ypos, button;
char arr[200], temp[5], *ptr;
char a[] = "C:\\Progra~1\\Mozill~1\\firefox ";
strcpy(arr,a);
i = strlen(a);
initialize_graphics_mode();
draw();
while(1)
{
if(kbhit())
key = get_key();
if((key>=97&&key<=122)||(key>=65&&key<=90)||key==46||key==47||key==63)
{
arr[i] = key;
sprintf(temp,"%c",arr[i]);
outtext(temp);
if(getx()>470)
{
clearviewport();
moveto(5,2);
}
i++;
}
else if ( key == 13 )
{
arr[i] = '\0';
system(arr);
break;
}
else if ( key == 27 )
{
closegraph();
exit(EXIT_SUCCESS);
}
if(button==1&&xpos>=150&&xpos<=480&&ypos>=300&&ypos<=330)
{
system("C:\\Progra~1\\Mozill~1\\firefox programmingsimplified.com");
break;
}
key = -1;
}
closegraph();
return 0;
}
void initialize_graphics_mode()
{
int gd = DETECT, gm, errorcode;
initgraph(&gd,&gm,"C:\\TURBOC3\\BGI");
errorcode = graphresult();
if( errorcode != grOk )
{
printf("Graphics error : %s\n",grapherrormsg(errorcode));
printf("Press any key to exit...\n");
getch();
exit(EXIT_FAILURE);
}
}
int get_key()
{
i.h.ah = 0;
int86(22,&i,&o);
return( o.h.al );
}
void draw()
{
settextstyle(SANS_SERIF_FONT,HORIZ_DIR,2);
outtextxy(275,11,"Web Browser");
outtextxy(155,451,"<a> href=http://www.programmingsimplified.com"">www.programmingsimplified.com</a>");
outtextxy(5,105,"Enter URL : ");
rectangle(120,100,600,130);
setviewport(121,101,599,129,1);
moveto(5,1);
}
Could someone help me in understanding why this happens? and possibly a fix for this?
NOTE: + It is supposed to work if you have Mozilla Firefox. If you have any other browser, please edit the code accordingly.
I am running this on Turbo C++, what would I have to do in order to convert this code for Dev-C++?
Thanks in advance.
P.S: I'm new to C++ so elaborate as much as possible.

NCURSES and Linux Input Device

I wrote a getSample(devicePath) function that reads raw input events from keyboard, however after running this function, ncurses doesn't display anything.
includes
#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#include <ncurses.h>
#include <vector>
#include <string>
getSample
const int KEY_PRESSED = 1;
const int KEY_RELEASED = 0;
std::vector<input_event> getSample(std::string devicePath) {
std::vector<input_event> events;
int fileDescriptor = open(devicePath.c_str(), O_RDONLY);
while (true) {
struct input_event event;
read(fileDescriptor, &event, sizeof(struct input_event));
if (event.type == EV_KEY)
if (event.value == KEY_PRESSED || event.value == KEY_RELEASED) {
if (event.code == 28 && event.value == KEY_PRESSED)
break;
events.push_back(event);
}
}
close(fileDescriptor);
return events;
}
main
int main() {
std::string devicePath = "/dev/input/by-id/"
"usb-Microsft_Microsoft_Wireless_Desktop_Receiver_3."
"1-event-kbd";
std::vector<input_event> sample = getSample(devicePath);
initscr();
printw("Hello World!");
refresh();
getch();
endwin();
return 0;
}
Is there a way to fix it?
Tip
Function getSample works correctly, because when I replace ncurses code with simple printf(), everything works fine
int main() {
std::string devicePath = "/dev/input/by-id/"
"usb-Microsft_Microsoft_Wireless_Desktop_Receiver_3."
"1-event-kbd";
std::vector<input_event> sample = getSample(devicePath);
for (unsigned int i = 0; i < sample.size(); i++)
printf("%d | %3d | %ld.%06ld\n", sample[i].value, sample[i].code,
(long)sample[i].time.tv_sec, (long)sample[i].time.tv_usec);
return 0;
}