Overloaded Methods in a class (arduino) - c++

Header code
/*
* MngCommunication.h
*
* Created on: 26 gen 2017
* Author: Giuliano
*/
#ifndef _MNGCOMMUNICATION_H_
#define _MNGCOMMUNICATION_H_
// ------------------------- N.B. MngCommunication is a Singleton class!!! ----------------------------
#if (ARDUINO < 100)
#include <WProgram.h>
#else
#include <Arduino.h>
#endif
class MngCommunication
{
public:
static MngCommunication* getInstance();
size_t LogLine(const __FlashStringHelper *ifsh, boolean end=false);
size_t LogLine(const String &str, boolean end=false);
size_t LogLine(const char str[], boolean end=false);
size_t LogLine(const unsigned char n, boolean end=false);
size_t LogLine(const int n, boolean end=false);
size_t LogLine(const unsigned int n, boolean end=false);
size_t LogLine(const long n, boolean end=false);
size_t LogLine(const unsigned long n, boolean end=false);
size_t LogLine(const double n, boolean end=false);
size_t LogLine(const Printable&str, boolean end=false);
protected:
static MngCommunication* _inst_;
MngCommunication();
};
#endif /* MNGCOMMUNICATION_MNGCOMMUNICATION_H_ */
C++ code
/*
* MngCommunication.cpp
*
* Created on: 26 gen 2017
* Author: Giuliano
*/
#include <string.h>
#include "MngCommunication.h"
MngCommunication* MngCommunication::_inst_ = NULL;
MngCommunication::MngCommunication()
{
Serial.begin(57600);
}
MngCommunication* MngCommunication::getInstance()
{
if (_inst_ == NULL) _inst_ = new MngCommunication;
return _inst_;
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// ------------------------ LOGGING FUNCTION -------------------------
//--------------------------------------------------------------------
//--------------------------------------------------------------------
boolean started=false;
inline size_t startLine(void)
{
static char timebuffer[8];
size_t sz = 0;
sprintf(timebuffer,"%08lu", millis());
sz += Serial.print("#L-");
sz += Serial.print(timebuffer);
sz += Serial.print("-");
started=true;
return sz;
}
inline size_t endline(void)
{
started = false;
return Serial.write("\r\n");
}
size_t MngCommunication::LogLine(const __FlashStringHelper *ifsh, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(ifsh);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const String &str, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(str);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const char str[], boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(str);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const unsigned char n, boolean end)
{
return LogLine((unsigned long) n, end);
}
size_t MngCommunication::LogLine(const int n, boolean end)
{
return LogLine((long) n, end);
}
size_t MngCommunication::LogLine(const unsigned int n, boolean end)
{
return LogLine((unsigned long) n, end);
}
size_t MngCommunication::LogLine(const long n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(n);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const unsigned long n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(n);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const double n, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(n);
if (end)
{
sz += endline();
}
return sz;
}
size_t MngCommunication::LogLine(const Printable&str, boolean end)
{
size_t sz=0;
if (!started)
{
sz += startLine();
started = true;
}
sz += Serial.print(str);
if (end)
{
sz += endline();
}
return sz;
}
If I use LogLine() function with string or char buffers, all is OK. e.g.:
MngCommunication* Comm;
Comm = MngCommunication::getInstance();
Comm.LogLine("this ");
Comm.LogLine("is ");
Comm.LogLine("a ");
Comm.LogLine("test!!! ", true);
The strange is the call with number:
if i call LogLine() with number e.g.:
MngCommunication* Comm;
Comm = MngCommunication::getInstance();
Comm.LogLine(millis());
code execution is OK. but a second call, with number or string, reboot Arduino. The same is if i call the function first with string and then with number. e.g.:
MngCommunication* Comm;
Comm = MngCommunication::getInstance();
Comm.LogLine("this ");
Comm.LogLine("is ");
Comm.LogLine("a ");
Comm.LogLine("test!!! ");
Comm.LogLine("time= ");
Comm.LogLine(mills());

static char timebuffer[8];
sprintf(timebuffer,"%08lu", millis());
First of all this buffer is too small. There has to be space for the string terminator (zero byte), so you have a buffer overflow which can cause all sort of strange effects.
This buffer should be at least 11 bytes long. 10 bytes for the max number (32 bit) and one for the string terminator.
I suppose mills() was a typo?
Do you have the same problem when using a constant value, like Comm.LogLine(123);?
And what if you call:
Comm.LogLine(123, true);
Comm.LogLine(456);

Related

C++ CycleBuffer unit test fail reason?

I have implement my CycleBuffer and run some unit tests. But it fails on a random read/write operation and I cannot find out why. Please help me. I use C++ 14 standard.
My CycleBuffer rely on libfmt and Catch2.
CycleBuffer.h
// Copyright 2019- <shepherd-lang>
// Apache License Version 2.0
#pragma once
#include <cstdio>
namespace detail {
/**
* CycleBuffer memory status
*
* positive: tail >= head
* 1)
* buf = head = tail = nullptr
*
* 2)
* head tail
* | |
* |-----------------------||
* |
* buf
*
* 3)
* head
* |
* |---------||-------------|
* | |
* buf tail
*
* 4)
* head tail
* | |
* |----|---------------|---|
* |
* buf
*
* negative: tail < head
* 1)
* tail head
* | |
* |----|---------------|---|
* |
* buf
*
* 2)
* tail head
* | |
* |----------------|-------|
* |
* buf
*
* 3)
* tail head
* | |
* |----|------------------||
* |
* buf
*
* 4)
* tail head
* | |
* |-----------------------||
* |
* buf
*
* impossible)
* tail head
* | |
* |------------------------|
* |
* buf
*/
template <unsigned int D> class CycleBuffer {
public:
CycleBuffer();
virtual ~CycleBuffer();
virtual int capacity() const;
virtual int size() const;
virtual bool empty() const;
virtual bool full() const;
virtual void reset();
// next position start from <position>
virtual char *next(char *position, int distance = 1) const;
virtual const char *next(const char *position, int distance = 1) const;
// previous position start from <position>
virtual char *prev(char *position, int distance = 1) const;
virtual const char *prev(const char *position, int distance = 1) const;
virtual char *begin();
virtual const char *begin() const;
virtual char *rbegin();
virtual const char *rbegin() const;
virtual char *end();
virtual const char *end() const;
virtual char *rend();
virtual const char *rend() const;
virtual bool contain(const char *position) const;
virtual std::string toString() const;
// write at most <n> bytes to <buf>
// #return bytes really write
virtual int write(char *buf, int n);
// read at most <n> bytes from <buf>
// #return bytes really read
virtual int read(const char *buf, int n);
// write all bytes to <fp>
// #return bytes really write
virtual int writefile(FILE *fp);
// write at most <n> bytes to <fp>
virtual int writefile(FILE *fp, int n);
// read all bytes from <fp>
// #return bytes really read
virtual int readfile(FILE *fp);
// read at most <n> bytes from <fp>
// #return bytes really read
virtual int readfile(FILE *fp, int n);
protected:
virtual char *nextImpl(char *position, int distance = 1) const;
virtual char *prevImpl(char *position, int distance = 1) const;
virtual void release();
virtual int expand(int n);
virtual char *bufEnd();
virtual const char *bufEnd() const;
// if positive direction
virtual bool positive() const;
// positive direction
virtual long pSize() const;
virtual bool pContain(const char *position) const;
// negative direction
virtual long nLeftSize() const;
virtual long nRightSize() const;
virtual bool nLeftContain(const char *position) const;
virtual bool nRightContain(const char *position) const;
virtual int writeImpl(void *src, int n,
int (*writeHandler)(void *, void *, int));
virtual int readImpl(void *src, int n,
int (*readHandler)(void *, void *, int, int));
char *buf_;
char *head_;
char *tail_;
int capacity_;
};
} // namespace detail
class DynamicBuffer : public detail::CycleBuffer<1> {
public:
DynamicBuffer(int capacity = 0);
virtual ~DynamicBuffer() = default;
virtual std::string toString() const;
};
class FixedBuffer : public detail::CycleBuffer<0> {
public:
FixedBuffer(int capacity);
virtual ~FixedBuffer() = default;
virtual std::string toString() const;
};
CycleBuffer.cpp
// Copyright 2019- <shepherd-lang>
// Apache License Version 2.0
#include "CycleBuffer.h"
#include "fmt/format.h"
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <tuple>
#define ALIGN(n) (n < 8 ? 8 : (n % 8 == 0 ? n : ((n / 8 + 1) * 8)))
#define MIN(a, b) (std::min<int>(a, b))
#define BUF_SIZE 1024
namespace detail {
template <unsigned int D> char *CycleBuffer<D>::bufEnd() {
return buf_ + capacity_;
}
template <unsigned int D> const char *CycleBuffer<D>::bufEnd() const {
return buf_ + capacity_;
}
// is positive direction
template <unsigned int D> bool CycleBuffer<D>::positive() const {
return tail_ >= head_;
}
template <unsigned int D> long CycleBuffer<D>::pSize() const {
return tail_ - head_;
}
template <unsigned int D>
bool CycleBuffer<D>::pContain(const char *position) const {
return position >= head_ && position < tail_;
}
template <unsigned int D> long CycleBuffer<D>::nLeftSize() const {
return tail_ - buf_;
}
template <unsigned int D> long CycleBuffer<D>::nRightSize() const {
return bufEnd() - head_;
}
template <unsigned int D>
bool CycleBuffer<D>::nLeftContain(const char *position) const {
return position >= buf_ && position < tail_;
}
template <unsigned int D>
bool CycleBuffer<D>::nRightContain(const char *position) const {
return position >= head_ && position < bufEnd();
}
template <unsigned int D>
CycleBuffer<D>::CycleBuffer()
: buf_(nullptr), head_(nullptr), tail_(nullptr), capacity_(0) {}
template <unsigned int D> CycleBuffer<D>::~CycleBuffer() { reset(); }
template <unsigned int D> int CycleBuffer<D>::capacity() const {
return capacity_ > 0 ? capacity_ - 1 : 0;
}
template <unsigned int D> int CycleBuffer<D>::size() const {
return positive() ? pSize() : (nLeftSize() + nRightSize());
}
template <unsigned int D> bool CycleBuffer<D>::empty() const {
return size() == 0;
}
template <unsigned int D> bool CycleBuffer<D>::full() const {
return size() == capacity();
}
template <unsigned int D> void CycleBuffer<D>::reset() {
release();
head_ = nullptr;
tail_ = nullptr;
capacity_ = 0;
}
template <unsigned int D>
char *CycleBuffer<D>::nextImpl(char *position, int distance) const {
if (position == end() || !position) {
return (char *)end();
}
char *np = position + distance;
if (positive()) {
return np > tail_ ? (char *)end() : np;
} else {
if (nLeftContain(position)) {
return np > tail_ ? (char *)end() : np;
} else {
if (np < bufEnd()) {
return np;
}
np = (char *)buf_ + (distance - (bufEnd() - position));
return np > tail_ ? (char *)end() : np;
}
}
}
template <unsigned int D>
char *CycleBuffer<D>::next(char *position, int distance) const {
return nextImpl(position, distance);
}
template <unsigned int D>
const char *CycleBuffer<D>::next(const char *position, int distance) const {
return nextImpl((char *)position, distance);
}
template <unsigned int D>
char *CycleBuffer<D>::prevImpl(char *position, int distance) const {
if (position == rend() || !position) {
return (char *)rend();
}
char *np = position - distance;
if (positive()) {
return np < head_ ? (char *)rend() : np;
} else {
if (nLeftContain(position)) {
if (np >= buf_) {
return np;
}
np = (char *)bufEnd() - (distance - (position - buf_));
return np < head_ ? (char *)rend() : np;
} else {
return np < head_ ? (char *)rend() : np;
}
}
}
template <unsigned int D>
char *CycleBuffer<D>::prev(char *position, int distance) const {
return prevImpl(position, distance);
}
template <unsigned int D>
const char *CycleBuffer<D>::prev(const char *position, int distance) const {
return prevImpl((char *)position, distance);
}
template <unsigned int D> char *CycleBuffer<D>::begin() { return head_; }
template <unsigned int D> const char *CycleBuffer<D>::begin() const {
return head_;
}
template <unsigned int D> char *CycleBuffer<D>::rbegin() {
return tail_ == buf_ ? bufEnd() - 1 : tail_ - 1;
}
template <unsigned int D> const char *CycleBuffer<D>::rbegin() const {
return tail_ == buf_ ? bufEnd() - 1 : tail_ - 1;
}
template <unsigned int D> char *CycleBuffer<D>::end() { return tail_; }
template <unsigned int D> const char *CycleBuffer<D>::end() const {
return tail_;
}
template <unsigned int D> char *CycleBuffer<D>::rend() { return head_ - 1; }
template <unsigned int D> const char *CycleBuffer<D>::rend() const {
return head_ - 1;
}
template <unsigned int D>
bool CycleBuffer<D>::contain(const char *position) const {
return positive() ? pContain(position)
: (nLeftContain(position) || nRightContain(position));
}
template <unsigned int D> std::string CycleBuffer<D>::toString() const {
return fmt::format("buf_:{}, head_:{}, tail_:{}, capacity_:{}", (void *)buf_,
(void *)head_, (void *)tail_, capacity_);
}
template <unsigned int D> void CycleBuffer<D>::release() {
if (buf_) {
std::free(buf_);
buf_ = nullptr;
}
}
static int writeMemHandler(void *src, void *buf, int n) {
std::memcpy(src, buf, n);
return n;
}
static int writeFileHandler(void *src, void *buf, int n) {
size_t r = std::fwrite(buf, 1, n, (FILE *)src);
return (int)r;
}
#define WINC(n) \
do { \
head_ = next(head_, n); \
writen += n; \
} while (0)
template <unsigned int D>
int CycleBuffer<D>::writeImpl(void *src, int n,
int (*writeHandler)(void *, void *, int)) {
EX_ASSERT(n >= 0, "n {} < 0", n);
if (!src || !n) {
return 0;
}
if (empty()) {
return 0;
}
int writen = 0;
if (positive()) {
int fn = MIN(size(), n);
int fnr = writeHandler(src, head_, fn);
WINC(fnr);
} else {
int fn = MIN(bufEnd() - head_, n);
int fnr = writeHandler(src, head_, fn);
WINC(fnr);
if (n > writen) {
int sn = MIN(n - writen, pSize());
int snr = writeHandler(src, head_, sn);
WINC(snr);
}
}
return writen;
}
template <unsigned int D> int CycleBuffer<D>::write(char *buf, int n) {
return writeImpl(buf, n, writeMemHandler);
}
template <unsigned int D> int CycleBuffer<D>::writefile(FILE *fp, int n) {
return writeImpl(fp, n, writeFileHandler);
}
template <unsigned int D> int CycleBuffer<D>::writefile(FILE *fp) {
int n = 0;
int tmp;
do {
tmp = writefile(fp, BUF_SIZE);
n += tmp;
} while (tmp > 0);
return n;
}
#define RINC(n) \
do { \
tail_ += n; \
readn += n; \
} while (0)
static int readMemHandler(void *src, void *buf, int n, int readn) {
char *src2 = (char *)src + readn;
std::memcpy(buf, src2, n);
return n;
}
static int readFileHandler(void *src, void *buf, int n, int readn) {
size_t r = std::fread(buf, 1, n, (FILE *)src);
return (int)r;
}
template <unsigned int D>
int CycleBuffer<D>::readImpl(void *src, int n,
int (*readHandler)(void *, void *, int, int)) {
if (!src || !n) {
return 0;
}
if (D) {
if (capacity() - size() < n) {
int c1 = capacity() + n + 1;
int c2 = capacity() * 2 + 1;
expand(c1 > c2 ? ALIGN(c1) : ALIGN(c2));
}
}
if (full()) {
return 0;
}
int readn = 0;
if (positive()) {
int fn = MIN(bufEnd() - tail_ - (head_ == buf_ ? 1 : 0), n);
int fnr = readHandler(src, tail_, fn, readn);
RINC(fnr);
if (tail_ == bufEnd()) {
tail_ = buf_;
}
if (n > readn && head_ != buf_) {
int sn = MIN(n - readn, head_ - tail_ - 1);
int snr = readHandler(src, tail_, sn, readn);
RINC(snr);
}
} else {
int fn = MIN(n, head_ - tail_ - 1);
int fnr = readHandler(src, tail_, fn, readn);
RINC(fnr);
}
return readn;
}
template <unsigned int D> int CycleBuffer<D>::read(const char *buf, int n) {
return readImpl((void *)buf, n, readMemHandler);
}
template <unsigned int D> int CycleBuffer<D>::readfile(FILE *fp, int n) {
return readImpl(fp, n, readFileHandler);
}
template <unsigned int D> int CycleBuffer<D>::readfile(FILE *fp) {
int n = 0;
int tmp;
do {
tmp = readfile(fp, BUF_SIZE);
n += tmp;
} while (tmp > 0);
return n;
}
template <unsigned int D> int CycleBuffer<D>::expand(int n) {
if (n <= capacity_) {
return 0;
}
char *newbuf = (char *)std::malloc(n);
if (!newbuf) {
return -1;
}
int sz = size();
if (positive()) {
std::memcpy(newbuf, head_, pSize());
} else {
std::memcpy(newbuf, head_, nRightSize());
std::memcpy(newbuf + nRightSize(), buf_, nLeftSize());
}
release();
buf_ = newbuf;
capacity_ = n;
head_ = buf_;
tail_ = buf_ + sz;
return 0;
}
} // namespace detail
DynamicBuffer::DynamicBuffer(int capacity) {
if (capacity > 0) {
expand(ALIGN(capacity + 1));
}
}
std::string DynamicBuffer::toString() const {
return fmt::format("[#DynamicBuffer {}]", detail::CycleBuffer<1>::toString());
}
FixedBuffer::FixedBuffer(int capacity) {
if (capacity > 0) {
// precise capacity
expand(capacity + 1);
}
}
std::string FixedBuffer::toString() const {
return fmt::format("[#FixedBuffer {}]", detail::CycleBuffer<0>::toString());
}
CycleBufferTest.cpp
// Copyright 2019- <shepherd-lang>
// Apache License Version 2.0
#include "CycleBuffer.h"
#include "catch2/catch.hpp"
#include "fmt/format.h"
#include <algorithm>
#include <cstdlib>
#define C_MIN 0
#define C_MAX 100
#define RAND (rand() % (C_MAX + 1))
TEST_CASE("container/CycleBuffer", "[container/CycleBuffer]") {
SECTION("random read/write") {
{
std::vector<char> v;
DynamicBuffer db;
int rc = 0, wc = 0;
for (int i = C_MIN; i < C_MAX; i++) {
int rn = RAND;
std::vector<char> rbuf(rn);
for (int j = 0; j < rn; j++) {
rbuf[j] = (char)rn;
v.push_back(rbuf[j]);
rc++;
LOG_INFO("DynamicBuffer random rbuf[{}]:{}", rc, (int)rbuf[j]);
}
REQUIRE(db.read(rbuf.data(), rn) == rn);
int wn = std::min(RAND, rn);
std::vector<char> wbuf(wn);
REQUIRE(db.write(wbuf.data(), wn) == wn);
for (int j = 0; j < wn; j++) {
LOG_INFO("DynamicBuffer random wbuf[{}]:{}", wc, (int)wbuf[j]);
if (wbuf[j] != v[wc]) {
LOG_INFO("DynamicBuffer random wbuf[{}]:{}", wc, (int)wbuf[j]); // here's the error place!
}
REQUIRE(wbuf[j] == v[wc]);
wc++;
}
}
}
}
}

How to Selection Sort some structs

I have to put in order some files sorting by year(ano), month(mes), day(dia) but i could only sort by year.
struct registro{
short ano;
char mes;
char dia;
char hora;
char min;
char seg;
};
void selectionSort(struct registro *dados, int n){
int i, j, menor;
struct registro aux;
for(i = 0; i < n - 1; i++){
menor = i;
for(j = i + 1; j < n; j++){
if(dados[menor].ano > dados[j].ano)
{
menor = j;
}
if(i != menor){
aux = dados[i];
dados[i] = dados[menor];
dados[menor] = aux;
}
}
}
}
Check signarturee of standard C library qsort function
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
As you can see the last parameter is a pointer to a function (callback) which is used to compare values. You are using fixed gretter operator dados[menor].ano > dados[j].ano in your selectionSort. In order to make it generic you can make next modification:
static registroYearCmp(struct registro* lhs, struct registro *rhs)
{
return lhs->ano - rhs->ano;
}
static registroMonthCmp(struct registro* lhs, struct registro *rhs)
{
return lhs->mes - rhs->mes;
}
static registroDayCmp(struct registro* lhs, struct registro *rhs)
{
return lhs->dia - rhs->dia;
}
void selectionSort(struct registro *dados, int n, *(compare_registro)(struct registro*, struct registro*) ){
......
if( compare_registro(dados[menor],dados[j]) > 0 )
......
}
.......
/* Sort by year */
selectionSort(dados, 16, registroYearCmp);
/* Sort by month */
selectionSort(dados, 16, registroMonthCmp);
/* Sort by day */
selectionSort(dados, 16, registroDayCmp);

Something wrong with char type in my code for EditDistance Recursive

I 'm reading "The Algorithm Design Manual (2nd Edition)". C++ is new for me.
I try to use example of author: string_compare(), and only code by myself main(). Output is wrong. I guess my main 's having problem with char s[], pointer.
Anyone can help me finding my mistake.
Code by C++, and very simple input
int main()
{
char s[] = "A"; // "thou shalt not"; //"FOOD";
char t[] = "B"; // "you should not"; //"MONEY";
int i = sizeof(s)/sizeof(char);
int j = sizeof(t)/sizeof(char);
int resultDistance = string_compare(s, t, i, j);
printf("N steps = %d\n", resultDistance);
reconstruct_path(s, t, i, j);
}
int string_compare(char *s, char *t, int i, int j)
{
int k; /* counter */
int opt[3]; /* cost of the three options */
int lowest_cost; /* lowest cost */
if (i == 0) return(j * indel(' '));
if (j == 0) return(i * indel(' '));
opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]);
opt[INSERT] = string_compare(s,t,i,j-1) + indel(t[j]);
opt[DELETE] = string_compare(s,t,i-1,j) + indel(s[i]);
lowest_cost = opt[MATCH];
for (k=INSERT; k<=DELETE; k++)
if (opt[k] < lowest_cost) lowest_cost = opt[k];
m[i][j].cost = lowest_cost; /* REMOVE FROM PRINTED VERSION */
return( lowest_cost );
}
int reconstruct_path(char *s, char *t, int i, int j)
{
/*printf("trace (%d,%d)\n",i,j);*/
if (m[i][j].parent == -1) return(0);
if (m[i][j].parent == MATCH) {
reconstruct_path(s,t,i-1,j-1);
match_out(s, t, i, j);
return(0);
}
if (m[i][j].parent == INSERT) {
reconstruct_path(s,t,i,j-1);
insert_out(t,j);
return(0);
}
if (m[i][j].parent == DELETE) {
reconstruct_path(s,t,i-1,j);
delete_out(s,i);
return(0);
}
}
int match_out(char *s, char *t, int i, int j)
{
if (s[i]==t[j]) printf("M");
else printf("S");
return(0);
}
void insert_out(char *t, int j)
{
printf("I");
}
void delete_out(char *s, int i)
{
printf("D");
}
int indel(char c)
{
return(1);
}
int match(char c, char d)
{
if (c == d) return(0);
else return(1);
}
My code on github: https://github.com/hoangvu1991/EditDistanceRecursive/blob/master/EditDistanceRecursive.cpp
actual: 0 | expect:1
Try following:
opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i-1],t[j-1]);
instead of
opt[MATCH] = string_compare(s,t,i-1,j-1) + match(s[i],t[j]);

va_arg not incrementing C++

I have a bug with my printf() function im implementing for OS. Basically the problem is, it dosent increment through the list. For example lets say i have:
printf("%d %d",19,58);
what will show on my OS is :
19 19
the 58 for some reason is not going thourgh. I have debugged this for quite some time, but cant find problem :( . Here is the stdio.c++:
#include "stdio.h"
static size_t terminal_row = 0;
static size_t terminal_column = 0;
static uint16_t* VideoMemory =((uint16_t*)0xb8000);
static bool continue_ex = false;
SerialPort sp_std_io;
void printf(char *str, ...)
{
va_list arg;
va_start(arg, str);
for(int32_t i=0;str[i]!='\0'; ++i)
{
putchar(str[i],str[i+1],arg);
}
va_end(arg);
}
void strcat(char *destination, const char *source)
{
int x = 0;
while (destination[x] != '\0')
{
x++;
}
for (int i=0; source[i] != '\0'; i++)
{
destination[x++] = source[i];
}
destination[x] = '\0';
}
void put_char_helper_neg(char chr)
{
const size_t index = (terminal_row * VGA_WIDTH + terminal_column);
terminal_column++;
VideoMemory[index]= (VideoMemory[index] & 0xFF00)|chr;
}
void putstring_t(char str)
{
size_t index = (terminal_row * VGA_WIDTH + terminal_column);
terminal_column++;
VideoMemory[index]= (VideoMemory[index] & 0xFF00)|str;
}
void putchar(char str,char next_str, va_list arg)
{
if(!continue_ex)
{
uint32_t ch_per;
char* str_use,str_use_space;
const char per = '%';
if(str == '\b')
{
terminal_column--;
}
const size_t index = (terminal_row * VGA_WIDTH + terminal_column);
char space = ' ';
switch(str)
{
case '\n':
terminal_row++;
terminal_column = 0;
break;
case '\b':
VideoMemory[index]= (VideoMemory[index] & 0xFF00)|space;
break;
case '%':
switch(next_str)
{
case 'd':
ch_per = va_arg(arg,int);
if(ch_per<0)
{
ch_per = -ch_per;
put_char_helper_neg('-');
}
str_use = itoa(ch_per);
terminal_column++;
for(int32_t i=0;str_use[i]!='\0'; ++i)
{
putstring_t(str_use[i]);
}
// sp_std_io.write_number_serial(ch_per);
// sp_std_io.write_string_serial(str_use);
continue_ex = true;
break;
default:
terminal_column++;
VideoMemory[index]= (VideoMemory[index] & 0xFF00)|per;
}
break;
default:
terminal_column++;
VideoMemory[index]= (VideoMemory[index] & 0xFF00)|str;
break;
}
}
else
{
continue_ex = false;
}
}
int32_t strlen(int8_t* str)
{
int32_t l=0;
while(str[l]!='\0')l++;
return l;
}
char *itoa(int val)
{
uint8_t *ptr;
static uint8_t buffer[16];
ptr = buffer + sizeof(buffer);
*--ptr = '\0';
if (val == 0)
{
*--ptr = '0';
}
else while (val != 0)
{
*--ptr = (val % 10) + '0';
val = val / 10;
}
return((char*)ptr);
}
and stdio.h:
#ifndef _STD_LIB_H_
#pragma once
#define _STD_LIB_H_ 1
#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>
#include "math.h"
#include "serial.h"
static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25;
//static int num_count_viedo_memory = 0;
void printf(char *str,...);
void putchar(char str,char next_str,va_list arg);
int32_t strlen(int8_t *str);
void strcat(char * Dest, char const * Src);
//int8_t* str_cat(int8_t *dest, const int8_t *src);
void reverse(char str[], int32_t length);
char* itoa(int val);
#endif
Like i described above , it is not incrementing through the args for some reason. Help would be appreciated! :)
Pass arg into your putchar function by reference instead of by value:
void putchar(char str,char next_str, va_list& arg)
What's happening is that it gets incremented inside your putchar function, but then the function returns and it has no effect on the variable in printf because putchar is passed a copy rather than a reference to it.

Struct keep values

I am trying to implement a struct to keep binary data. Just like this:
struct Buffer {
int size_;
int capacity = 1000000;
int beg_index, end_index;
char data_[1000000];
} buffer_audio[3];
And a function to write the binary data in the buffer:
int writing_bufer(Buffer buffers, const char *data, int nbytes) {
if (nbytes == 0) return 0;
int capacity = buffers.capacity;
int bytes_to_write = std::min(nbytes, capacity - buffers.size_);
if (bytes_to_write <= capacity - buffers.end_index)
{
memcpy(buffers.data_ + buffers.end_index, data, bytes_to_write);
buffers.end_index += bytes_to_write;
if (buffers.end_index == capacity) buffers.end_index = 0;
}
else { return 0; }
buffers.size_ += bytes_to_write;
return bytes_to_write;
}
But the problem is.. Every time I run this routine the values of beg_index and end_index are deleted. And the memcpy will overwrite.
The routine:
void buffering_mem(char* chunk,int size_chunk, int close_file, int client, int total_size){
int check_bytes = writing_bufer(buffer_audio[client], chunk, size_chunk);
//other code
}
int writing_bufer(Buffer buffers, const char *data, int nbytes)
should be
int writing_bufer(Buffer& buffers, const char *data, int nbytes)
You copied buffers into the function and filled the local buffers and then destroyed them.