Oii,tou este server mas não está calculando direito alguem me pode ajudar
O primeiro grande problema que eu identifiquei
Você não inicializou a variável n
e isso afeta esta linha:
double x[n], y[n];
Pois não dá pra saber que tamanho x e y teria, poderia ser até mesmo 0.
E afeta também seus loops, porque você coloca i < n
, então eles nunca executam.
Então sua primeira correção deve ser inicializar a variavel x
.
E isso nos leva ao próximo grande erro que é o fato de que os arrays x
e y
também não foram inicializados.
Com base nas observações acima eu modifiquei sua função, ficou assim:
void *linearregression(void *arg) {
int *newsockfd = (int *)arg;
string string1(buffer);
string string2(previousBuffer);
int n = 5;
double x[n] = {1, 2, 4, 3, 5};
double y[n] = {1, 3, 3, 2, 5};
double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;
for (int i = 0; i < n; i++) {
cout << "x[" << i << "] = ";
cout << "y[" << i << "] = ";
}
for (int i = 0; i < n; i++) {
xsum = xsum + x[i]; // calculate sigma(xi)
ysum = ysum + y[i]; // calculate sigma(yi)
x2sum = x2sum + pow(x[i], 2); // calculate sigma(x^2i)
xysum = xysum + x[i] * y[i]; // calculate sigma(xi*yi)
}
double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
double a = (ysum - b * xsum) / n;
cout << "\nCalculated value of a is " << a << "and b is " << b << '\n';
cout << "Equation of best fit is: y = " << a << " + " << b << " x";
return NULL;
}
Eu compilei com este comando:
g++ main.cpp -lpthread && ./a.out
E testei usando curl
com esse comando:
curl http://localhost:65432
E o resultado foi esse:
GET / HTTP/1.1
Host: localhost:65432
User-Agent: curl/7.65.3
Accept: */*
x[0] = y[0] = x[1] = y[1] = x[2] = y[2] = x[3] = y[3] = x[4] = y[4] =
Calculated value of a is 0.4and b is 0.8
Equation of best fit is: y = 0.4 + 0.8 x n
*******************************************************************************
Eu fiquei na dúvida em 2 coisas:
Dúvidas 1: Pra quê serve o loop abaixo?
for (int i = 0; i < n; i++) {
cout << "x[" << i << "] = ";
cout << "y[" << i << "] = ";
}
Dúvidas 2: Eu usei o valor 5 para n
e uns valores quaisquer pra x
e y
, mas de onde virão esses valores na verdade?
Muito obrigada por me ajudar
Eu acho que encontrei a solução. No caso vc passaria os valores de x e y através da URL.
Por exemplo, no navegador, vc acessaria este endereço:
http://localhost:65432/?x=1,10.56,3,434.300&y=3,3,4.5,12.3
Percebeu que os valores são separados por uma virgula?
Dá pra acessar pela linha de comando também usando o curl assim:
curl "http://localhost:65432?x=1,2,3,4&y=3,3,4.5,12.3"
O código abaixo foi compilado com o seguinte comando:
g++ main.cpp -Wall -Wextra -Wpedantic -lpthread
Veja como ficou:
#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>
int client;
void error(const char *message) {
perror(message);
exit(EXIT_FAILURE);
}
void pargeArg(const char *arg, std::vector<double> &x, std::vector<double> &y) {
std::string str((const char *)arg);
std::smatch m;
std::regex r("([xy])=([0-9,.]+)");
while (std::regex_search(str, m, r)) {
auto &curr = m[1] == "x" ? x : y;
std::stringstream ss(m[2]);
std::string substr;
while (std::getline(ss, substr, ',')) curr.push_back(std::stod(substr));
str = m.suffix().str();
}
}
void *test(void *arg) {
std::vector<double> x;
std::vector<double> y;
pargeArg((const char *)arg, x, y);
int n = x.size();
double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;
for (int i = 0; i < n; i++) {
xsum = xsum + x[i]; // calculate sigma(xi)
ysum = ysum + y[i]; // calculate sigma(yi)
x2sum = x2sum + pow(x[i], 2); // calculate sigma(x^2i)
xysum = xysum + x[i] * y[i]; // calculate sigma(xi*yi)
}
double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
double a = (ysum - b * xsum) / n;
std::string response("HTTP/1.1 200 OK\n\nCalculated value of A is: " +
std::to_string(a) + " and B is: " + std::to_string(b) +
"\n"
"Equation of best fit is: y = " +
std::to_string(a) + " + " + std::to_string(b) + "x\n");
send(client, response.c_str(), response.length(), 0);
std::cout << response << std::endl;
return NULL;
}
int main() {
constexpr int PORT = 65432;
constexpr int SIZE = 1024;
char buffer[SIZE];
pthread_t s;
sockaddr_in addrIn = {AF_INET, htons(PORT), INADDR_ANY, 0};
sockaddr *addr = (sockaddr *)&addrIn;
socklen_t addrlen = sizeof(addrIn);
const int server = socket(AF_INET, SOCK_STREAM, 0);
const int optName = SO_REUSEADDR | SO_REUSEPORT;
const int opt = 1;
const socklen_t len = sizeof(opt);
if (server == 0) error("socket failed");
if (setsockopt(server, SOL_SOCKET, optName, &opt, len)) error("setsockopt");
if (bind(server, addr, addrlen) < 0) error("Bind failed");
if (listen(server, 3) < 0) error("listen");
while (true) {
if ((client = accept(server, addr, &addrlen)) < 0) error("accept");
read(client, buffer, SIZE);
pthread_create(&s, NULL, test, buffer);
pthread_join(s, NULL);
close(client);
}
close(server);
return 0;
}
g++ main.cpp -Wall -Wextra -Wpedantic
Eu usei as opção -Wall -Wextra -Wpedantic
na hora de compilar apenas para me certificar de que o código estava correto. Vc pode compilar com o comando que vc mostrou normalmente.
Vc nem chegou a testar o código que mostrei antes de falar que não é compativel e saber se funciona?
Imagino que os valores de x e y venha de uma lugar, como vc não deu maiores detalhes, eu escrevi o código considerando que esses valores viriam da URL, mas isso pode ser facilmente alterado.
Por favor, me explique detalhadamente de onde vem os valores de x e y.
Aqui já seria outro problema. Se vc quer salvar os dados, vc pode criar um arquivo de texto simples contendo os valores.
Sim
O programa 7-regression
é o cliente? Vc poderia me mostrar o código fonte dele?
Sim
Acho que entendi.
Eu rodei o cliente com o seguinte comando:
./7-regression localhost 1000
E parece que deu, olha como ficou:
#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <regex>
#include <string>
constexpr int PORT = 65432;
std::vector<double> x;
std::vector<double> y;
void error(const char *message) {
perror(message);
exit(EXIT_FAILURE);
}
void pargeArg(const char *arg, std::vector<double> &x, std::vector<double> &y) {
std::string str(arg);
std::size_t comma = str.find(',');
x.push_back(std::stod(str.substr(0, comma)));
y.push_back(std::stod(str.substr(comma + 1)));
}
void *linearregression(void *arg) {
pargeArg((const char *)arg, x, y);
const int n = x.size();
double xsum = 0, x2sum = 0, ysum = 0, xysum = 0;
for (int i = 0; i < n; i++) {
xsum = xsum + x[i]; // calculate sigma(xi)
ysum = ysum + y[i]; // calculate sigma(yi)
x2sum = x2sum + pow(x[i], 2); // calculate sigma(x^2i)
xysum = xysum + x[i] * y[i]; // calculate sigma(xi*yi)
}
double b = (n * xysum - xsum * ysum) / (n * x2sum - xsum * xsum);
double a = (ysum - b * xsum) / n;
std::string response("Calculated value of A is: " + std::to_string(a) +
" and B is: " + std::to_string(b) +
"\n"
"Equation of best fit is: y = " +
std::to_string(a) + " + " + std::to_string(b) + "x\n");
std::cout << response << std::endl;
return NULL;
}
int main() {
constexpr int SIZE = 1024;
char buffer[SIZE];
std::cout << "Started..." << std::endl;
pthread_t s;
sockaddr_in addrIn = {AF_INET, htons(PORT), INADDR_ANY, 0};
sockaddr *addr = (sockaddr *)&addrIn;
socklen_t addrlen = sizeof(addrIn);
int server, client;
const int optName = SO_REUSEADDR | SO_REUSEPORT;
const int opt = 1;
const socklen_t len = sizeof(opt);
if ((server = socket(AF_INET, SOCK_STREAM, 0)) == 0) error("socket failed");
if (setsockopt(server, SOL_SOCKET, optName, &opt, len)) error("setsockopt");
if (bind(server, addr, addrlen) < 0) error("Bind failed");
if (listen(server, 3) < 0) error("listen");
if ((client = accept(server, addr, &addrlen)) < 0) error("accept");
while (read(client, buffer, SIZE) > 0) {
pthread_create(&s, NULL, linearregression, buffer);
pthread_join(s, NULL);
}
close(client);
close(server);
return 0;
}