win32 socket bind func fails with error 10014 c++ - windows

I am trying to run a tcp server on my machine, this is mostly a tutorial code but for some reason the bind is failing with error 10014. sizeof(serverAddr) returns 16 in the below code if anyone is interested. I know what error 10014 means but can't seem to figure out why it's coming here on bind everything seems ok.
#include <iostream>
#include <winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
int main()
{
WSADATA WSAData;
SOCKET server, client;
SOCKADDR_IN serverAddr, clientAddr;
int iResult = WSAStartup(MAKEWORD(2, 2), &WSAData);
if (iResult != NO_ERROR) {
std::cout << "startup error" << std::endl;
return 1;
}
server = socket(AF_INET, SOCK_STREAM, 0);
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(5555);
if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr) != 0))
{
std::cout << "bind " << WSAGetLastError() << " sizeof " << sizeof(serverAddr) << std::endl;
std::cout << "cannot start server" << std::endl;
return 0;
}
listen(server, 0);
std::cout << "Listening for incoming connections..." << std::endl;
char buffer[1024];
int clientAddrSize = sizeof(clientAddr);
if ((client = accept(server, (SOCKADDR*)&clientAddr, &clientAddrSize)) != INVALID_SOCKET)
{
std::cout << "Client connected!" << std::endl;
recv(client, buffer, sizeof(buffer), 0);
std::cout << "Client says: " << buffer << std::endl;
memset(buffer, 0, sizeof(buffer));
closesocket(client);
std::cout << "Client disconnected." << std::endl;
}
return 0;
}

There is an error with the parantheses. This line:
if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr) != 0))
Shoud be:
if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) != 0)

Related

WSAEFAULT 10014, Why setsockopt returning -1?

My setsockopt() call is returning -1, I used WSAGetLastError() which returns WSAEFAULT.
WSAEFAULT
10014
Bad address.
The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a sockaddr structure, is smaller than the sizeof(sockaddr).
I am using MSVC 2022
#include<iostream>
#include<WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
#define PORT 9909
struct sockaddr_in srv;
fd_set fr, fw, fe;
int nMaxFd;
int main() {
int nRet = 0;
// Initialize the WSA variables
WSADATA ws;
if (WSAStartup(MAKEWORD(2, 2), &ws) < 0) {
cout << endl << "WSA failed to initialize";
WSACleanup();
exit(EXIT_FAILURE);
}
else
cout << endl << "WSA initialized";
// Initialize the socket
int nSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (nSocket < 0) {
cout << endl << "The socket not opened";
WSACleanup();
exit(EXIT_FAILURE);
}
else {
cout << endl << "The socket opened successfully"<<nSocket;
}
// Initialize the environment for sockaddr structure
srv.sin_family = AF_INET;
srv.sin_port = htons(PORT);
srv.sin_addr.s_addr = INADDR_ANY;
memset(srv.sin_zero, 0, 8);
// setsockpot
int nOptVal = 1;
int nOptLen = sizeof(nOptVal);
nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)nOptVal, nOptLen);
cout << nRet;
if (!nRet) {
cout << endl << "The setsockopt call successful";
}
else {
cout << endl << "THe setsockopt call failed";
cout << endl << WSAGetLastError();
WSACleanup();
exit(EXIT_FAILURE);
}
/* In default, every socket is Blocking socket, we have to use explicitly if wer want non blocking sockets
// About the Blocking and Non Blocking sockets
u_long optval = 0;
nRet = ioctlsocket(nSocket, FIONBIO, &optval);
if (nRet != 0) {
cout << endl << "ioctlsocket call failed";
}
else {
cout << endl << "ioctlsocket call passed";
}
*/
/*
// Bind the socket to the local port
nRet = bind(nSocket, (sockaddr*)&srv, sizeof(sockaddr));
if (nRet < 0) {
cout << endl << "Fail to bind to local port";
exit(EXIT_FAILURE);
}
else
cout << endl << "Successfully bind to local port";
// Listen the request from client (queues the requests)
nRet = listen(nSocket, 5);
if (nRet < 0) {
cout << endl << "Fail to start listen to local port";
WSACleanup();
exit(EXIT_FAILURE);
}
else {
cout << endl << "Started listening to local port";
}
nMaxFd = nSocket;
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
while (1) {
FD_ZERO(&fr);
FD_ZERO(&fw);
FD_ZERO(&fe);
FD_SET(nSocket, &fr);
FD_SET(nSocket, &fe);
cout << endl << "Before select call: " << fr.fd_count;
// Keep waiting for new requests and proceed as per the request
nRet = select(nMaxFd + 1, &fr, &fw, &fe, &tv);
if (nRet > 0) {
// When someone connects or communicates with a message over a dedicated connection
}
else if (nRet == 0) {
// No connection or any communication request made or you can say that none of the
// socket descriptors are ready
cout << endl << "Nothing on port: " << PORT;
}
else {
// It failed and your application should show some useful message
cout << endl << "I failed...";
WSACleanup();
exit(EXIT_FAILURE);
}
cout << endl << "After the select call: " << fr.fd_count;
}
*/
}
I assumed my setsockopt() will return 0, but it returns -1:
int nOptVal = 1;
int nOptLen = sizeof(nOptVal);
nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)nOptVal, nOptLen);
Per the setsockopt() documentation, the WSAEFAULT error is telling you that you are passing in an invalid pointer in the optval parameter:
Error code
Meaning
WSAEFAULT
The buffer pointed to by the optval parameter is not in a valid part of the process address space or the optlen parameter is too small.
When calling setsockopt(), you need to pass in the memory address of the nOptVal variable, but you are passing in its value instead, typecasted to a pointer. 1 is not a valid memory address of the variable, hence the error.
Try this instead:
int nOptVal = 1;
int nOptLen = sizeof(nOptVal);
nRet = setsockopt(nSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&nOptVal, nOptLen);
^
add this!

ffmpeg avcodec_send_packet/avcodec_receive_frame memory leak

I'm attempting to decode frames, but memory usage grows with every frame (more specifically, with every call to avcodec_send_packet) until finally the code crashes with a bad_alloc. Here's the basic decode loop:
int rfret = 0;
while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){
if (packet.stream_index == vstrm_idx) {
//std::cout << "Sending Packet" << std::endl;
int ret = avcodec_send_packet(ctx.get(), &packet);
if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
std::cout << "avcodec_send_packet: " << ret << std::endl;
break;
}
while (ret >= 0) {
//std::cout << "Receiving Frame" << std::endl;
ret = avcodec_receive_frame(ctx.get(), fr);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
//std::cout << "avcodec_receive_frame: " << ret << std::endl;
av_frame_unref(fr);
// av_frame_free(&fr);
break;
}
std::cout << "frame: " << ctx->frame_number << std::endl;
// eventually do something with the frame here...
av_frame_unref(fr);
// av_frame_free(&fr);
}
}
else {
//std::cout << "Not Video" << std::endl;
}
av_packet_unref(&packet);
}
Memory usage/leakage seems to scale with the resolution of the video I'm decoding. For example, for a 3840x2160 resolution video, the memory usage in windows task manager consistently jumps up by about 8mb (1 byte per pixel??) for each received frame. Do I need to do something besides call av_frame_unref to release the memory?
(more) complete code below
void AVFormatContextDeleter(AVFormatContext* ptr)
{
if (ptr) {
avformat_close_input(&ptr);
}
}
void AVCodecContextDeleter(AVCodecContext* ptr)
{
if (ptr) {
avcodec_free_context(&ptr);
}
}
typedef std::unique_ptr<AVFormatContext, void (*)(AVFormatContext *)> AVFormatContextPtr;
typedef std::unique_ptr<AVCodecContext, void (*)(AVCodecContext *)> AVCodecContextPtr;
AVCodecContextPtr createAvCodecContext(AVCodec *vcodec)
{
AVCodecContextPtr ctx(avcodec_alloc_context3(vcodec), AVCodecContextDeleter);
return ctx;
}
AVFormatContextPtr createFormatContext(const std::string& filename)
{
AVFormatContext* inctxPtr = nullptr;
int ret = avformat_open_input(&inctxPtr, filename.c_str(), nullptr, nullptr);
// int ret = avformat_open_input(&inctx, "D:/Videos/test.mp4", nullptr, nullptr);
if (ret != 0) {
inctxPtr = nullptr;
}
return AVFormatContextPtr(inctxPtr, AVFormatContextDeleter);
}
int testDecode()
{
// open input file context
AVFormatContextPtr inctx = createFormatContext("D:/Videos/Matt Chapman Hi Greg.MOV");
if (!inctx) {
// std::cerr << "fail to avforamt_open_input(\"" << infile << "\"): ret=" << ret;
return 1;
}
// retrieve input stream information
int ret = avformat_find_stream_info(inctx.get(), nullptr);
if (ret < 0) {
//std::cerr << "fail to avformat_find_stream_info: ret=" << ret;
return 2;
}
// find primary video stream
AVCodec* vcodec = nullptr;
const int vstrm_idx = av_find_best_stream(inctx.get(), AVMEDIA_TYPE_VIDEO, -1, -1, &vcodec, 0);
if (vstrm_idx < 0) {
//std::cerr << "fail to av_find_best_stream: vstrm_idx=" << vstrm_idx;
return 3;
}
AVCodecParameters* origin_par = inctx->streams[vstrm_idx]->codecpar;
if (vcodec == nullptr) { // is this even necessary?
vcodec = avcodec_find_decoder(origin_par->codec_id);
if (!vcodec) {
// Can't find decoder
return 4;
}
}
AVCodecContextPtr ctx = createAvCodecContext(vcodec);
if (!ctx) {
return 5;
}
ret = avcodec_parameters_to_context(ctx.get(), origin_par);
if (ret) {
return 6;
}
ret = avcodec_open2(ctx.get(), vcodec, nullptr);
if (ret < 0) {
return 7;
}
//print input video stream informataion
std::cout
//<< "infile: " << infile << "\n"
<< "format: " << inctx->iformat->name << "\n"
<< "vcodec: " << vcodec->name << "\n"
<< "size: " << origin_par->width << 'x' << origin_par->height << "\n"
<< "fps: " << av_q2d(ctx->framerate) << " [fps]\n"
<< "length: " << av_rescale_q(inctx->duration, ctx->time_base, {1,1000}) / 1000. << " [sec]\n"
<< "pixfmt: " << av_get_pix_fmt_name(ctx->pix_fmt) << "\n"
<< "frame: " << inctx->streams[vstrm_idx]->nb_frames << "\n"
<< std::flush;
AVPacket packet;
av_init_packet(&packet);
packet.data = nullptr;
packet.size = 0;
AVFrame *fr = av_frame_alloc();
if (!fr) {
return 8;
}
int rfret = 0;
while((rfret = av_read_frame(inctx.get(), &packet)) >= 0){
if (packet.stream_index == vstrm_idx) {
//std::cout << "Sending Packet" << std::endl;
int ret = avcodec_send_packet(ctx.get(), &packet);
if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
std::cout << "avcodec_send_packet: " << ret << std::endl;
break;
}
while (ret >= 0) {
//std::cout << "Receiving Frame" << std::endl;
ret = avcodec_receive_frame(ctx.get(), fr);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
//std::cout << "avcodec_receive_frame: " << ret << std::endl;
av_frame_unref(fr);
// av_frame_free(&fr);
break;
}
std::cout << "frame: " << ctx->frame_number << std::endl;
// do something with the frame here...
av_frame_unref(fr);
// av_frame_free(&fr);
}
}
else {
//std::cout << "Not Video" << std::endl;
}
av_packet_unref(&packet);
}
std::cout << "RFRET = " << rfret << std::endl;
return 0;
}
Update 1: (1/21/2019) Compiling on a different machine and running with different video files I am not seeing the memory usage growing without bound. I'll try to narrow down where the difference lies (compiler?, ffmpeg version?, or video encoding?)
Update 2: (1/21/2019) Ok, it looks like there is some interaction occurring between ffmpeg and Qt's QCamera. In my application, I'm using Qt to manage the webcam, but decided to use ffmpeg libraries to handle decoding/encoding since Qt doesn't have as comprehensive support for different codecs. If I have the camera turned on (through Qt), ffmpeg decoding memory consumption grows without bound. If the camera is off, ffmpeg behaves fine. I've tried this both with a physical camera (Logitech C920) and with a virtual camera using OBS-Virtualcam, with the same result. So far I'm baffled as to how the two systems are interacting...
I had same problem.
before use the av_frame_unref.
call av_freep(buffer->data[0]).
av_frame_unref was not release raw data in frame
example:
av_freep(&pFrame->data[0]);
av_frame_unref(pFrame);
//av_free(pFrame);
EDIT:
I am sorry that English is immature.
When you decode the video, you have the data for the image in the buffer.
It will remain as a NULL pointer until you release it and reallocate it, which means that you will need to allocate memory again at reallocation.
After you have finished using the image data, you should release the buffer.
Are you using it like that?
while (Framecheck = av_read_frame(pFormatCtx, &packet) == NULL ) {
if (d_end == true)
break;
if (packet.stream_index == VSI) {
if (bool res = avcodec_send_packet(pVideoCodecCtx, &packet)) {
printf("avcodec_send_packet failed %d %d %d\n", res, AVERROR(EINVAL), AVERROR(ENOMEM));
}
if (bool res = avcodec_receive_frame(pVideoCodecCtx, pVFrame) == 0) {
printf("avcodec_receive failed %d %d %d\n", res, AVERROR(EINVAL), AVERROR(ENOMEM));
}
if (pVFrame->data[0] == NULL && pVFrame->data[1] == NULL && pVFrame->data[2] == NULL)
continue;
else {
YUV_frame = Con_yuv_RGB(pVFrame);
QFrame->push(YUV_frame);
PushCount++;
}
}
Sleep(5);
}
if (Framecheck != true){
av_packet_unref(&packet);
d_end = true;
return true;
release:
if (FrameQueue->size()) {
while (FrameQueue->size() > 0) {
av_freep(&FrameQueue->front());
//av_frame_unref(FrameQueue->front());
av_free(FrameQueue->front());
FrameQueue->pop();
}
}
Try calling av_frame_free when you're done with the frame (outside your while loop)
And don't call av_frame_unref
See example here:
https://ffmpeg.org/doxygen/4.0/decode__video_8c_source.html

TCP buffer parameters not being honoured on Win7 machine

Note: I have tagged this with both programming and windows networking tags, so please don't shout, I'm just trying to expose this to as many people as may be able to help!
I am trying to set the receive and send buffers for a small client and server I have written, so that when I perform a network capture, I see the window size I have set in the TCP handshake.
For the programmers, please consider the following very simple code for a client and server.
For the none-programmers, please skip past this section to my image.
Client:
#include <WinSock2.h>
#include <mstcpip.h>
#include <Ws2tcpip.h>
#include <thread>
#include <iostream>
using namespace std;
int OutputWindowSize(SOCKET s, unsigned int nType)
{
int buflen = 0;
int nSize = sizeof(buflen);
if (getsockopt(s, SOL_SOCKET, nType, (char *)&buflen, &nSize) == 0)
return buflen;
return -1;
}
bool SetWindowSizeVal(SOCKET s, unsigned int nSize)
{
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&nSize, sizeof(nSize)) == 0)
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&nSize, sizeof(nSize)) == 0)
return true;
return false;
}
int main(int argc, char** argv)
{
if (argc != 3) { cout << "not enough args!\n"; return 0; }
const char* pszHost = argv[1];
const int nPort = atoi(argv[2]);
WSADATA wsaData;
DWORD Ret = 0;
if ((Ret = WSAStartup((2, 2), &wsaData)) != 0)
{
printf("WSAStartup() failed with error %d\n", Ret);
return 1;
}
struct sockaddr_in sockaddr_IPv4;
memset(&sockaddr_IPv4, 0, sizeof(struct sockaddr_in));
sockaddr_IPv4.sin_family = AF_INET;
sockaddr_IPv4.sin_port = htons(nPort);
if (!InetPtonA(AF_INET, pszHost, &sockaddr_IPv4.sin_addr)) { return 0; }
SOCKET clientSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create active socket: one which is passed to connect().
if (!SetWindowSizeVal(clientSock, 12345))
{
cout << "Failed to set window size " << endl;
return -1;
}
cout << "Set window size on client socket as: RECV" << OutputWindowSize(clientSock, SO_RCVBUF) <<
" SEND: " << OutputWindowSize(clientSock, SO_SNDBUF) << endl;
int nRet = connect(clientSock, (sockaddr*)&sockaddr_IPv4, sizeof(sockaddr_in));
if (nRet != 0) { return 0; }
char buf[100] = { 0 };
nRet = recv(clientSock, buf, 100, 0);
cout << "Received " << buf << " from the server!" << endl;
nRet = send(clientSock, "Hello from the client!\n", strlen("Hello from the client!\n"), 0);
closesocket(clientSock);
return 0;
}
Server:
#include <WinSock2.h>
#include <mstcpip.h>
#include <Ws2tcpip.h>
#include <iostream>
using namespace std;
int OutputWindowSize(SOCKET s, unsigned int nType)
{
int buflen = 0;
int nSize = sizeof(buflen);
if (getsockopt(s, SOL_SOCKET, nType, (char *)&buflen, &nSize) == 0)
return buflen;
return -1;
}
bool SetWindowSizeVal(SOCKET s, unsigned int nSize)
{
if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&nSize, sizeof(nSize)) == 0)
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&nSize, sizeof(nSize)) == 0)
return true;
return false;
}
int main()
{
WSADATA wsaData;
DWORD Ret = 0;
if ((Ret = WSAStartup((2, 2), &wsaData)) != 0)
{
printf("WSAStartup() failed with error %d\n", Ret);
return 1;
}
struct sockaddr_in sockaddr_IPv4;
memset(&sockaddr_IPv4, 0, sizeof(struct sockaddr_in));
sockaddr_IPv4.sin_family = AF_INET;
sockaddr_IPv4.sin_port = htons(19982);
int y = InetPton(AF_INET, L"127.0.0.1", &sockaddr_IPv4.sin_addr);
if (y != 1) return 0;
socklen_t addrlen = sizeof(sockaddr_IPv4);
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!SetWindowSizeVal(sock, 12345))
{
cout << "Failed to set window size " << endl;
return -1;
}
cout << "Set window size on listen socket as: RECV" << OutputWindowSize(sock, SO_RCVBUF) <<
" SEND: " << OutputWindowSize(sock, SO_SNDBUF) << endl;
if (bind(sock, (sockaddr*)&sockaddr_IPv4, sizeof(sockaddr_IPv4)) != 0) { /* error */ }
if (listen(sock, SOMAXCONN) != 0) { return 0; }
while (1)
{
SOCKET sockAccept = accept(sock, (struct sockaddr *) &sockaddr_IPv4, &addrlen);
if (!SetWindowSizeVal(sockAccept, 12345))
{
cout << "Failed to set window size " << endl;
return -1;
}
cout << "Set window size as on accepted socket as: RECV" << OutputWindowSize(sock, SO_RCVBUF) <<
" SEND: " << OutputWindowSize(sock, SO_SNDBUF) << endl;
if (sockAccept == -1) return 0;
int nRet = send(sockAccept, "Hello from the server!\n", strlen("Hello from the server!\n"), 0);
if (!nRet) return 0;
char buf[100] = { 0 };
nRet = recv(sockAccept, buf, 100, 0);
cout << "Received " << buf << " from the client!" << endl;
if (nRet == 0) { cout << "client disonnected!" << endl; }
closesocket(sockAccept);
}
return 0;
}
The output from my program states that the window sizes have been set succesfully:
Set window size on listen socket as: RECV12345 SEND: 12345
Set window size as on accepted socket as: RECV12345 SEND: 12345
for the server, and for the client:
Set window size on listen socket as: RECV12345 SEND: 12345
However, when I capture the traffic using RawCap, I see that the client window size is set fine, but server's window size is not what I set it to be, it is 8192:
Now, I have read this MS link and it says to add a registry value; I did this, adding the value 0x00001234, but it still made no difference.
The interesting thing is, the same code works fine on a Windows 10 machine, which makes me think it is Windows 7 specific. However, I'm not 100% sure on my code, there might be some errors in it.
Can anyone suggest how I can get Windows to honour my requested parameters please?
These are not 'window sizes'. They are send and receive buffer sizes.
There is no such thing as 'output window size'. There is a receive window and a congestion window, and the latter is not relevant to your question.
The send buffer size has exactly nothing to do with the receive window size, and the receive buffer size only determines the maximum receive window size.
The actual receive window size is adjusted dynamically by the protocol. It is the actual size that you are seeing in Wireshark.
The platform is entitled by the specification to adjust the supplied values for the send and receive buffers up or down, and the documentation advises you to get the corresponding values if you want to be sure what they really are.
There is no problem here to solve.
NB You don't have to set the receive window size on an accepted socket if you already set it on the listening socket. It is inherited.

C++ .txt read in issues. getline reading full file

first of all, forgive my code for being ugly. The tons of ideas I've been given to try to fix this code have jumbled it up after all the potential solutions that haven't worked. Basically, I'm coding a Hearthstone rip-off that reads in two .txt files with card information and battles them to see which player wins. The issue is that when I'm trying to save the player's name (the first line in the files), it saves the whole file instead of just the first line. When I have managed to fix that, the for loop used to save the information for the card objects (format: card name, card power, card health) does not get saved properly for some reason. Any help would be appreciated, I've been trying to fix this for two days and nothing has fully solved the problem. I'll attach the read in files first before the code.
Disclaimer: It's a lot of lines and I'm sorry about that. Also I think the problem could be that my Mac is not saving the .txt in a format that has the right line endings. I'm using XCode as my IDE. Thank you so much to whomever is willing to help!
File1:
The Innkeeper
3
Tunnel Trogg
1
3
Neptulon
7
7
Fire Elemental
6
5
File2:
Malfurion
3
Leper Gnome
2
1
Aviana
5
5
Cenarius
5
8
Main:
#include "Player.h"
using namespace std;
int main()
{
cout << "Please enter file name of the first player: " << endl;
string inFile = "";
getline(cin, inFile);
Player* p1 = new Player(inFile);
cout << "Now enter the file name of the second player: " << endl;
getline(cin, inFile);
Player* p2 = new Player(inFile);
p1->battle(*p2);
delete p1;
delete p2;
return 0;
}
Player Header:
#include "Card.h"
#include <fstream>
#ifndef Player_h
#define Player_h
using namespace std;
class Player
{
private:
string playerName;
int numCards;
Card ** cards;
int wins = 0;
public:
Player(std::string inFile);
void battle(Player p2);
Card* getCard(int counter);
~Player();
};
#endif /* Player_h */
Card Header:
#include <string>
#include <iostream>
#ifndef Card_h
#define Card_h
using namespace std;
class Card
{
public:
Card();
string getName();
int getPower();
int getHealth();
void setName(string newName);
void setPower(int newPower);
void setHealth(int newHealth);
Card* duel(Card&);
friend ostream& operator<<(ostream& o, Card& c);
friend bool operator==(Card& p1Card, Card& p2Card);
private:
string name;
int power;
int health;
};
#endif /* Card_h */
Player Source:
#include "Player.h"
using namespace std;
Player::Player(string inFile)
{
ifstream in(inFile, ios::in);\
if (!in)
{
cerr << "There was a problem opening the file. Sorry, try again!" << endl;
return;
}
getline(in, playerName);
cout << playerName << endl;
in>>numCards;
playerName = "";
numCards = 0;
cards = new Card* [numCards];
string tempName = "";
int tempPower = 0;
int tempHealth = 0;
for (int i = 0; i<numCards; i++)
{
in.ignore();
cards[i] = new Card();
getline(in, tempName);
cout << "in for loop: " << endl;
cout << tempName << ",";
cards[i]->setName(tempName);
in >> tempPower;
in.ignore();
cout << tempPower << ",";
cards[i]->setPower(tempPower);
in >> tempHealth;
cout << tempHealth << " done"<< endl;
cards[i]->setHealth(tempHealth);
}
}
void Player::battle(Player p2)
{
int draws = 0;
cout << "Let the battle begin!" << endl;
cout << numCards << endl;
if (wins > p2.wins)
{
cout << playerName << " wins over " << p2.playerName << ", " << wins << " to " << p2.wins;
if (draws == 0)
{
cout << " and no ties." << endl;
}
else
{
cout << " and " << draws << " ties." << endl;
}
}
else if (p2.wins > wins)
{
cout << p2.playerName << " wins over " << playerName << ", " << p2.wins << " to " << wins;
if (draws == 0)
{
cout << " and no ties." << endl;
}
else
{
cout << " and " << draws << " ties." << endl;
}
}
else if (p2.wins == wins)
{
cout << "It is a draw between " << playerName << " and " << p2.playerName << ", with " << wins << " for each and ";
if (draws == 0)
{
cout << "no ties." << endl;
}
else
{
cout << draws << " ties." << endl;
}
}
cout << "Here are the detailed results:" << endl;
for (int i = 0; i < numCards; i++)
{
cout << *cards[i] << " vs. " << *p2.cards[i] << " - ";
if (*cards[i] == *p2.cards[i])
{
cout << "It is a draw." << endl;
}
else if (cards[i]->duel(*p2.cards[i]) == NULL)
{
cout << "It is a draw." << endl;
}
else if (*cards[i]->duel(*p2.cards[i]) == *p2.cards[i])
{
cout << p2.cards[i]->getName() << "wins for " << p2.playerName << "." << endl;
}
else if (*cards[i]->duel(*p2.cards[i]) == *cards[i])
{
cout << cards[i]->getName() << "wins for " << playerName << "." << endl;
}
}
}
Player::~Player()
{
if (cards != NULL)
{
for (int i = 0; i < numCards; i++)
{
if (cards[i] != nullptr)
{
delete cards[i];
cards[i] = NULL;
}
};
}
}
Card Source:
#include "Card.h"
using namespace std;
Card::Card()
{
name = "";
power = 0;
health = 0;
}
string Card::getName()
{
return name;
}
int Card::getPower()
{
return power;
}
int Card::getHealth()
{
return health;
}
void Card::setName(string newName)
{
name = newName;
}
void Card::setPower(int newPower)
{
power = newPower;
}
void Card::setHealth(int newHealth)
{
health = newHealth;
}
Card* Card::duel(Card& otherCard)
{
if ((otherCard.getHealth() - this->getPower() <=0) && (getHealth() - otherCard.getPower() <= 0))
{
return NULL;
}
else if ((otherCard.getHealth() - this->getPower() >0) && (getHealth() - otherCard.getPower() >0))
{
return NULL;
}
else if (otherCard.getHealth() - this->getPower() <=0)
{
return this;
}
else if (this->getHealth() - otherCard.getPower() <=0)
{
return &otherCard;
}
return NULL;
}
ostream& operator<<(ostream& o, Card& c)
{
o << c.getName() << " (" << c.power << ", " << c.health << ") " << endl;
return o;
}
bool operator==(Card& p1Card, Card& p2Card)
{
if (p1Card.health == p2Card.health &&
p1Card.power == p2Card.power &&
p1Card.name == p2Card.name)
{
return true;
}
else
{
return false;
}
}
Your code is almost right. It can read the Player's name and the card numbers, but your codes showed below:
in>>numCards;
playerName = "";
numCards = 0;
cards = new Card* [numCards];
at first, it read the num of card and store it to numCards, it is right.
next, you clear the value of the numCards, then, you lost the num of the Card, so the codes followed it are executed with numCards == 0
You can just comment the line numCards = 0, and your code is executed right.

Why the audio recorder code can work for 8 bit, but cannot work for 16 bit??

I am trying to record the audio at windows, here is my code. it works well for 8 bit, but it cannot work for 16 bit. Can anyone help me?
#include
#include
#include
#pragma comment(lib,"winmm.lib")
using namespace std;
int test(){
HWAVEIN microHandle;
WAVEHDR waveHeader;
MMRESULT result = 0;
WAVEFORMATEX waveformat;
waveformat.wFormatTag = WAVE_FORMAT_PCM;
waveformat.wBitsPerSample=8;
waveformat.nSamplesPerSec=16000;//8000;
waveformat.nAvgBytesPerSec=waveformat.nSamplesPerSec*waveformat.nSamplesPerSec/8;
waveformat.nChannels=1;
waveformat.nBlockAlign=waveformat.nChannels*waveformat.wBitsPerSample/8;
waveformat.cbSize=0;
result = waveInOpen(&microHandle, WAVE_MAPPER, &waveformat, 0L, 0L, CALLBACK_EVENT);
if (result)
{
cout << "Fail step 1" << endl;
cout << result << endl;
Sleep(10000);
return 0;
}
const int BUFSIZE = 16000*4;
char * buf = (char *)malloc(BUFSIZE);
// Set up and prepare header for input
waveHeader.lpData = (LPSTR)buf;
waveHeader.dwBufferLength = BUFSIZE;
waveHeader.dwBytesRecorded=0;
waveHeader.dwUser = 0L;
waveHeader.dwFlags = 0L;
waveHeader.dwLoops = 0L;
waveInPrepareHeader(microHandle, &waveHeader, sizeof(WAVEHDR));
// Insert a wave input buffer
result = waveInAddBuffer(microHandle, &waveHeader, sizeof(WAVEHDR));
if (result)
{
cout << "Fail step 2" << endl;
cout << result << endl;
Sleep(10000);
return 0;
}
result = waveInStart(microHandle);
if (result)
{
cout << "Fail step 3" << endl;
cout << result << endl;
Sleep(10000);
return 0;
}
// Wait until finished recording
do {} while (waveInUnprepareHeader(microHandle, &waveHeader, sizeof(WAVEHDR))==WAVERR_STILLPLAYING);
FILE *fp = fopen("output.pcm","w");
fwrite(buf,1,BUFSIZE,fp);
fclose(fp);
waveInClose(microHandle);
return 0;
}
void main()
{
test();
}
If I set the parameter waveformat.wBitsPerSample = 8, it can record the audio correctly,
but if i set it waveformat.wBitsPerSample = 16, it record the Noise!!!
Can anyone help me?
thanks.
it should bu FILE *fp = fopen("output.pcm","wb"); NOT FILE *fp = fopen("output.pcm","w");

Resources