Is this usage of arg ok? - qt

msg.append(QString("\"settime\": %1000,") .arg(eventList[i].failureBegin)); // set time
I would like to know if it`s ok to have %1 right next to 000. Since there is only 1 argument then there is obviously no confusion possible for QString but what if I had 10 .arg() Then it would confuse it with %10 right? Is there an escape sequence for this or do I have to break it down into concatenations?

It is not ok. You can explore the source code of QString::arg or let me show you.
QString QString::arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const
{
ArgEscapeData d = findArgEscapes(*this);
if (d.occurrences == 0) {
qWarning() << ""QString::arg: Argument missing:"" << *this << ',' << a;
return *this;
}
//.... something not important.
}
This is how findArgEscapes is implemented. I think source code of Qt is much more readable than most STL implementations.
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break;
const QChar *escape_start = c;
if (++c == uc_end)
break;
bool locale_arg = false;
if (c->unicode() == 'L') {
locale_arg = true;
if (++c == uc_end)
break;
}
int escape = c->digitValue();
if (escape == -1)
continue;
++c;
if (c != uc_end) {
int next_escape = c->digitValue();
if (next_escape != -1) {
escape = (10 * escape) + next_escape; //*************
++c;
}
}
if (escape > d.min_escape)
continue;
if (escape < d.min_escape) {
d.min_escape = escape;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
}
++d.occurrences;
if (locale_arg)
++d.locale_occurrences;
d.escape_len += c - escape_start;
}
return d;
}

Related

TLE on UVA 10776 - Determine The Combination

I tried this problem by backtracking and did some optimization, though I am getting TLE. what further optimization can I do on this code?
Abridged problem statement - Task is to print all different r combinations of a string s (a r combination of a string s is a collection of exactly r letters from different positions in s).There may be different permutations of the same combination; consider only the one that has its r
characters in non-decreasing order. If s = "abaa" and s = 3.Then output should be (aaa,aab).
My code(in c)
int compare_chars(const void* a, const void* b);
char s[50];
int len;
int r ;
char combination[50];
void combinate(int index,int at)
{
if(at == r)
{
combination[at] = '\0';
puts(combination);
return ;
}
int i = index+1;
for ( ; i <= len-r+at ;)
{
char temp = s[I];
combination[at] = temp;
combinate(i,at+1);
while(s[i] == temp and i <= len-r+at)
i++;
}
return ;
}
int solve()
{
while ((scanf("%s %i",s,&r)) == 2)
{
len = strlen(s);
if(len == r)
{
printf("%s\n",s);
continue;
}
qsort(s,len,sizeof(char),compare_chars);
combinate(-1,0);
}
return 0;
}
int main()
{
int a = 1;
int t = 1;
while (a <= t)
{
int kk = solve();
}
return 0;
}
int compare_chars(const void* a, const void* b)
{
char arg1 = *(const char*)a;
char arg2 = *(const char*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}

How to convert Ximea xiAPI camera data into QImage?

I have data from a camera in mono 8bit.
This is converted into an int vector using
std::vector<int> grayVector(size);
// convert / copy pointer data into vector: 8 bit
if (static_cast<XI_IMG_FORMAT>(format) == XI_MONO8)
{
quint8* imageIterator = reinterpret_cast<quint8*> (pMemVoid);
for (size_t count = 0; count < size; ++count)
{
grayVector[count] = static_cast<int>(*imageIterator);
imageIterator++;
}
}
Next, I need to convert this into a QImage. If I set the image format to QImage::Format_Mono the app crashes. With QImage::Format_RGB16 I get strippes, and with QImage::Format_RGB32 everything is black.
I would like to know how to do this the best, efficient and correct way?
// convert gray values into QImage data
QImage image = QImage(static_cast<int>(sizeX), static_cat<int>(sizeY), QImage::Format_RGB16);
for ( int y = 0; y < sizeY; ++y )
{
int yoffset = sizeY*y;
QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(y)) ;
for ( int x = 0; x < sizeX ; ++x )
{
int pos = x + yoffset;
int color = grayVector[static_cast<size_t>(pos)];
*line++ = qRgb(color, color, color);
}
}
The conversion to int is unnecessary and you do it in a very inefficient way; all you need is to use the QImage::Format_Grayscale8 available since Qt 5.5 (mid-2015).
Anyway, what you really want is a way to go from XI_IMG to QImage. The default BP_UNSAFE buffering policy should be adequate - the QImage will do a format conversion, so taking the data from XiApi's internal buffer is OK. Thus the following - all of the conversions are implemented in Qt and are quite efficient - much better than most any naive code.
I didn't check whether some Xi formats may need a BGR swap. If so, then the swap can be set to true in the format selection code and the rest will happen automatically.
See also: xiAPI manual.
static QVector<QRgb> grayScaleColorTable() {
static QVector<QRgb> table;
if (table.isEmpty()) {
table.resize(256);
auto *data = table.data();
for (int i = 0; i < table.size(); ++i)
data[i] = qRgb(i, i, i);
}
return table;
}
constexpr QImage::Format grayScaleFormat() {
return (QT_VERSION >= QT_VERSION_CHECK(5,5,0))
? QImage::Format_Grayscale8
: QImage::Format_Indexed8;
}
QImage convertToImage(const XI_IMG *src, QImage::Format f) {
Q_ASSERT(src->fmt == XI_MONO16);
Q_ASSERT((src->padding_x % 2) == 0);
if (src->fmt != XI_MONO16) return {};
const quint16 *s = static_cast<const quint16*>(src->bp);
const int s_pad = src->padding_x/2;
if (f == QImage::Format_BGR30 ||
f == QImage::Format_A2BGR30_Premultiplied ||
f == QImage::Format_RGB30 ||
f == QImage::Format_A2RGB30_Premultiplied)
{
QImage ret{src->width, src->height, f};
Q_ASSERT((ret->bytesPerLine() % 4) == 0);
const int d_pad = ret->bytesPerLine()/4 - ret->width();
quint32 *d = (quint32*)ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000 | v << 20 | v << 10 | v;
}
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000u | v << 20 | v << 10 | v;
}
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage ret{src->width, src->height, grayScaleFormat()};
const int d_pad = ret->bytesPerLine() - ret->width();
auto *d = ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
*d++ = (*s++) >> 8;
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i)
*d++ = (*s++) >> 8;
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage fromXiImg(const XI_IMG *src, QImage::Format dstFormat = QImage::Format_ARGB32Premultiplied) {
Q_ASSERT(src->width > 0 && src->height > 0 && src->padding_x >= 0 && src->bp_size > 0);
Q_ASSERT(dstFormat != QImage::Format_Invalid);
bool swap = false;
int srcPixelBytes = 0;
bool externalConvert = false;
QImage::Format srcFormat = QImage::Format_Invalid;
switch (src->fmt) {
case XI_MONO8:
srcPixelBytes = 1;
srcFormat = grayScaleFormat();
break;
case XI_MONO16:
srcPixelBytes = 2;
externalConvert = true;
break;
case XI_RGB24:
srcPixelBytes = 3;
srcFormat = QImage::Format_RGB888;
break;
case XI_RGB32:
srcPixelBytes = 4;
srcFormat = QImage::Format_RGB32;
break;
};
if (srcFormat == QImage::Format_Invalid && !externalConvert) {
qWarning("Unhandled XI_IMG image format");
return {};
}
Q_ASSERT(srcPixelBytes > 0 && srcPixelBytes <= 4);
int bytesPerLine = src->width * srcPixelBytes + src->padding_x;
if ((bytesPerLine * src->height - src->padding_x) > src->bp_size) {
qWarning("Inconsistent XI_IMG data");
return {};
}
QImage ret;
if (!externalConvert)
ret = QImage{static_cast<const uchar*>(src->bp), src->width, src->height,
bytesPerLine, srcFormat};
else
ret = convertToImage(src, dstFormat);
if (ret.format() == QImage::Format_Indexed8)
ret.setColorTable(grayScaleColorTable());
if (ret.format() != dstFormat)
ret = std::move(ret).convertToFormat(dstFormat);
if (swap)
ret = std::move(ret).rgbSwapped();
if (!ret.isDetached()) // ensure that we don't share XI_IMG's data buffer
ret.detach();
return ret;
}

Vulkan swapchain with 0 extent

I've stumbled upon a strange behavior inside my Vulkan application (based on Qt, but it shouldn't matter).
When my Vulkan window gets resized I need to recreate the swapchain. I use vkGetPhysicalDeviceSurfaceCapabilitiesKHR() to get new information about the window surface (which is not being recreated, which might or might not be a problem) and receive the new surface extents: currentExtent = { 46, 0 } with minImageExtent = { 1, 1 }. In other words, Vulkan wants me to create a 0 height swapchain while simultaneously 1x1 being the minimum allowed.
Assuming that the driver knows what it's doing, I proceed along and later I get a debug report stating that some internal "vkCreateImage failed", and after that Vulkan crashes leaving only death and destruction. How to handle that? Should I constrain currentExtent to min and max? Or am I missing something?
EDIT:
As the comments suggest, I'm copy-pasting parts of the code responsible for this. What I've noticed is that the OS actually resizes the window to 46x0 at some point, for some reason.
void QtWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
scheduleSwapchainRecreation();
}
void QtWindow::scheduleSwapchainRecreation()
{
std::lock_guard<std::mutex> lock{mSwapchainRecreationMutex};
if (mSwapchainRecreationScheduled)
return;
mSwapchainRecreationScheduled = true;
QMetaObject::invokeMethod(this, "recreateSwapchain", Qt::QueuedConnection);
}
void QtWindow::recreateSwapchain()
{
std::lock_guard<std::mutex> lock{mStateMutex};
checkVkResult(vkDeviceWaitIdle(mDevice));
createSwapchain();
// state mutex should also cover swapchain recreation
mSwapchainRecreationScheduled = false;
}
void QtWindow::createSwapchain()
{
mSwapchain = makeUnique<VulkanSwapchain>(mMemoryManager,
width(),
height(),
mInstance,
mPhysicalDevice,
mDevice,
mSurface,
mPresentationQueueFamily,
mPresentationQueue,
mMemoryManager,
mSwapchain.get());
const auto min = mSwapchain->getMinExtent();
const auto max = mSwapchain->getMaxExtent();
setMinimumSize({ static_cast<int>(min.width), static_cast<int>(min.height) });
setMaximumSize({ static_cast<int>(max.width), static_cast<int>(max.height) });
}
The swapchain class:
VulkanSwapchain::VulkanSwapchain(uint32_t width,
uint32_t height,
VkInstance instance,
VkPhysicalDevice physicalDevice,
const VulkanDevice &device,
VkSurfaceKHR surface,
uint32_t presentationQueueFamily,
VkQueue presentationQueue,
const MemoryManagerPtr &memoryManager,
VulkanSwapchain *oldSwapchain)
: mInstance{instance}
, mDevice{device}
, mSurface{surface}
, mPresentQueue{presentationQueue}
, mDetails{{},{{}, memoryManager},{{}, memoryManager}}
, mSwapchainImages{memoryManager}
, mSwapchainImageViews{memoryManager}
, mMainCommandBuffers{memoryManager}
{
createSwapchain(width, height, physicalDevice, presentationQueueFamily, memoryManager, oldSwapchain);
createSwapchainImageViews();
createSemaphores();
createMainCommandPool();
}
VulkanSwapchain::~VulkanSwapchain()
{
if (mMainCommandPool != VK_NULL_HANDLE)
vkDestroyCommandPool(mDevice, mMainCommandPool, nullptr);
vkDestroySemaphore(mDevice, mAcquireSemaphore, nullptr);
for (const auto view : mSwapchainImageViews)
vkDestroyImageView(mDevice, view, nullptr);
if (mSwapchain != VK_NULL_HANDLE)
vkDestroySwapchainKHR(mDevice, mSwapchain, nullptr);
if (mSurface != VK_NULL_HANDLE)
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
}
VkResult VulkanSwapchain::acquire() noexcept
{
return vkAcquireNextImageKHR(mDevice, mSwapchain, UINT64_MAX, mAcquireSemaphore, VK_NULL_HANDLE, &mAcquiredImageIndex);
}
VkResult VulkanSwapchain::present(VkSemaphore renderingFinishedSemaphore) noexcept
{
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &renderingFinishedSemaphore;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &mSwapchain;
presentInfo.pImageIndices = &mAcquiredImageIndex;
return vkQueuePresentKHR(mPresentQueue, &presentInfo);
}
void VulkanSwapchain::createSwapchain(uint32_t width,
uint32_t height,
VkPhysicalDevice physicalDevice,
uint32_t presentationQueueFamily,
const MemoryManagerPtr &memoryManager,
VulkanSwapchain *oldSwapchain)
{
GE_LOG << L"Creating swapchain..." << std::endl;
querySwapchainDetails(physicalDevice);
chooseSwapchainSurfaceFormat();
const auto chosenPresentMode = chooseSwapchainPresentMode();
chooseSwapchainExtents(width, height);
// triple or double buffering
auto imageCount = (chosenPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) ? (3u) : (2u);
if (imageCount < mDetails.mCapabilities.minImageCount)
imageCount = mDetails.mCapabilities.minImageCount;
else if (mDetails.mCapabilities.maxImageCount > 0 && imageCount > mDetails.mCapabilities.maxImageCount)
imageCount = mDetails.mCapabilities.maxImageCount;
GE_LOG << L"Chosen surface format: " << mSwapchainFormat.format << L' ' << mSwapchainFormat.colorSpace << std::endl;
GE_LOG << L"Chosen present mode: " << chosenPresentMode << std::endl;
GE_LOG << L"Chosen extents: " << mExtent.width << L'x' << mExtent.height << std::endl;
GE_LOG << L"Image count: " << imageCount << std::endl;
VkSwapchainCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = mSurface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = mSwapchainFormat.format;
createInfo.imageColorSpace = mSwapchainFormat.colorSpace;
createInfo.imageExtent = mExtent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
createInfo.preTransform = mDetails.mCapabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
createInfo.presentMode = chosenPresentMode;
createInfo.clipped = VK_TRUE;
if (oldSwapchain != nullptr)
createInfo.oldSwapchain = *oldSwapchain;
const auto graphicsQueueFamily = mDevice.getGraphicsQueueFamily();
if (graphicsQueueFamily != presentationQueueFamily)
{
uint32_t queueFamilyIndices[] = { graphicsQueueFamily, presentationQueueFamily };
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else
{
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
}
checkVkResult(vkCreateSwapchainKHR(mDevice, &createInfo, nullptr, &mSwapchain));
uint32_t swapchainImageCount = 0;
checkVkResult(vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount, nullptr));
mSwapchainImages.resize(swapchainImageCount);
checkVkResult(vkGetSwapchainImagesKHR(mDevice, mSwapchain, &swapchainImageCount, mSwapchainImages.data()));
}
void VulkanSwapchain::querySwapchainDetails(VkPhysicalDevice physicalDevice)
{
checkVkResult(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, &mDetails.mCapabilities));
uint32_t numSurfaceFormats = 0;
checkVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &numSurfaceFormats, nullptr));
if (numSurfaceFormats == 0)
BOOST_THROW_EXCEPTION(RenderingModule::Exception{"Cannot find surface formats."});
mDetails.mSurfaceFormats.resize(numSurfaceFormats);
checkVkResult(vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, mSurface, &numSurfaceFormats, mDetails.mSurfaceFormats.data()));
uint32_t numPresentModes = 0;
checkVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface, &numPresentModes, nullptr));
if (numPresentModes == 0)
BOOST_THROW_EXCEPTION(RenderingModule::Exception{"Cannot find presentation modes."});
mDetails.mPresentModes.resize(numPresentModes);
checkVkResult(vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, mSurface, &numPresentModes, mDetails.mPresentModes.data()));
}
void VulkanSwapchain::chooseSwapchainExtents(uint32_t width, uint32_t height)
{
if (mDetails.mCapabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
mExtent.width = mDetails.mCapabilities.currentExtent.width;
else
mExtent.width = std::min(std::max(mDetails.mCapabilities.minImageExtent.width, width), mDetails.mCapabilities.maxImageExtent.width);
if (mDetails.mCapabilities.currentExtent.height != std::numeric_limits<uint32_t>::max())
mExtent.height = mDetails.mCapabilities.currentExtent.height;
else
mExtent.height = std::min(std::max(mDetails.mCapabilities.minImageExtent.height, height), mDetails.mCapabilities.maxImageExtent.height);
}
void VulkanSwapchain::chooseSwapchainSurfaceFormat()
{
VkSurfaceFormatKHR desiredSurfaceFormat = { VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR };
if (mDetails.mSurfaceFormats.size() == 1 && mDetails.mSurfaceFormats[0].format == VK_FORMAT_UNDEFINED)
{
mSwapchainFormat = desiredSurfaceFormat;
}
else
{
auto found = false;
for (const auto &format : mDetails.mSurfaceFormats)
{
if (format.format == desiredSurfaceFormat.format && format.colorSpace == desiredSurfaceFormat.colorSpace)
{
mSwapchainFormat = format;
found = true;
break;
}
}
if (!found)
{
// try without color space
for (const auto &format : mDetails.mSurfaceFormats)
{
if (format.format == desiredSurfaceFormat.format)
{
mSwapchainFormat = format;
found = true;
break;
}
}
if (!found)
mSwapchainFormat = mDetails.mSurfaceFormats.front();
}
}
}
void VulkanSwapchain::createSwapchainImageViews()
{
mSwapchainImageViews.resize(mSwapchainImages.size());
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = mSwapchainFormat.format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.layerCount = 1;
for (auto i = 0u; i < mSwapchainImages.size(); ++i)
{
createInfo.image = mSwapchainImages[i];
checkVkResult(vkCreateImageView(mDevice, &createInfo, nullptr, &mSwapchainImageViews[i]));
}
}
void VulkanSwapchain::createSemaphores()
{
VkSemaphoreCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
checkVkResult(vkCreateSemaphore(mDevice, &createInfo, nullptr, &mAcquireSemaphore));
}
void VulkanSwapchain::createMainCommandPool()
{
VkCommandPoolCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
createInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
createInfo.queueFamilyIndex = mDevice.getGraphicsQueueFamily();
checkVkResult(vkCreateCommandPool(mDevice, &createInfo, nullptr, &mMainCommandPool));
mMainCommandBuffers.resize(mSwapchainImageViews.size());
VkCommandBufferAllocateInfo allocateInfo = {};
allocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocateInfo.commandPool = mMainCommandPool;
allocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocateInfo.commandBufferCount = static_cast<uint32_t>(mMainCommandBuffers.size());
checkVkResult(vkAllocateCommandBuffers(mDevice, &allocateInfo, mMainCommandBuffers.data()));
}
VkPresentModeKHR VulkanSwapchain::chooseSwapchainPresentMode() const
{
VkPresentModeKHR chosenPresentMode = VK_PRESENT_MODE_FIFO_KHR;
QSettings settings;
if (!settings.value(swapIntervalSettingName, true).toBool())
{
for (const auto mode : mDetails.mPresentModes)
{
if (mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
{
chosenPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
break;
}
}
}
#if (defined(Q_OS_WIN) && !defined(Q_OS_WINPHONE)) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
else if (settings.value(tripleBufferingSettingName, true).toBool())
{
// reduce latency on desktops, but preserve battery life on mobile
for (const auto mode : mDetails.mPresentModes)
{
if (mode == VK_PRESENT_MODE_MAILBOX_KHR)
{
chosenPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
break;
}
}
}
#endif
return chosenPresentMode;
}

how to tokenize a string in arduino

i am using arduino due. what i am trying to do is to receive a string at serial. like this one:
COMSTEP 789 665 432 END
if the string starts with comstep, then to tokenize the string and get an integer array {789, 665, 432}.
is there anyway to do that?
P.S: im a noob at programming, so any help is appreciated.
I have a function that I wrote long ago to parse strings up in an easy manner. It is in use on several of my Arduino projects.
Sample usage:
char pinStr[3];
char valueStr[7];
int pinNumber, value;
getstrfld (parms_in, 0, 0, (char *)",", pinStr);
getstrfld (parms_in, 1, 0, (char *)",", valueStr);
pinNumber = atoi (pinStr);
value = atoi (valueStr);
The functions:
// My old stand-by to break delimited strings up.
char * getstrfld (char *strbuf, int fldno, int ofset, char *sep, char *retstr)
{
char *offset, *strptr;
int curfld;
offset = strptr = (char *)NULL;
curfld = 0;
strbuf += ofset;
while (*strbuf) {
strptr = !offset ? strbuf : offset;
offset = strpbrk ((!offset ? strbuf : offset), sep);
if (offset) {
offset++;
} else if (curfld != fldno) {
*retstr = 0;
break;
}
if (curfld == fldno) {
strncpy (retstr, strptr,
(int)(!offset ? strlen (strptr)+ 1 :
(int)(offset - strptr)));
if (offset)
retstr[offset - strptr - 1] = 0;
break;
}
curfld++;
}
return retstr;
}
// Included because strpbrk is not in the arduino gcc/g++ libraries
// Or I just could not find it :)
char * strpbrk (const char *s1, const char *s2)
{
const char *c = s2;
if (!*s1) {
return (char *) NULL;
}
while (*s1) {
for (c = s2; *c; c++) {
if (*s1 == *c)
break;
}
if (*c)
break;
s1++;
}
if (*c == '\0')
s1 = NULL;
return (char *) s1;
}
A light-weight approach (no strict checks on valid parses of the integers and ignoring any list elements past a fixed maximum):
char buf[32] = "COMSTEP 789 665 432 END"; // assume this has just been read
int res[8], nres = 0;
bool inlist = false;
for (char *p = strtok(buf, " "); p; p = strtok(0, " "))
if (inlist)
{
if (!strcmp(p, "END"))
{
inlist = false;
break;
}
else if (nres < sizeof(res) / sizeof(*res))
res[nres++] = atoi(p);
}
else if (!strcmp(p, "COMSTEP"))
inlist = true;
if (!inlist)
for (size_t i = 0; i < nres; ++i)
printf("%d%s", res[i], i + 1 < nres ? " " : "\n"); // do whatever

Convert a string from UART to hex value in c

I am working on pic controllers. I have a string "040F" which is sent to the controller through UART.
I want to convert this string to a hex representation such as 0x040F. I tried a code snippet but no success.
Can anyone please help me out.
If what you mean is to convert a hex string to binary, the below code can help. It may not be an optimized one and may be other simpler solutions are available in the internet and can be even buggy. But it will give you some idea, I hope.
#include<stdio.h>
#include<string.h>
#define MAX_STR_LEN 16
int hex_char_to_bin(char ch)
{
if(ch >= '0' && ch <= '9')
{
return (ch - '0');
}
else if(ch >= 'a' && ch <= 'f')
{
return (10 + ch - 'a');
}
else if(ch >= 'A' && ch <= 'F')
{
return (10 + ch - 'A');
}
return -1;
}
int hex_str_to_bin(const char *hex_str, int *result)
{
int str_len, i;
int bin_val = 0;
str_len = strnlen(hex_str, MAX_STR_LEN);
for (i = 0; i < str_len; i++)
{
int val = hex_char_to_bin(*hex_str++);
if (val == -1)
return -1;
bin_val = (bin_val<<4) + val;
}
*result = bin_val;
return 0;
}
int main()
{
char str[] = "043f";
int hex;
if(!hex_str_to_bin(str, &hex))
printf("%x\n",hex);
else
printf("Invalid hex charecters in string\n");
return 0;
}

Resources