问:
Multiple characters replace in Linux using sed
I have a variable in Linux like below. This is not a valid variable I just created to test how to replace characters with some new characters.

```<code>table=123~!@#$%^&*()+|}{:"?><-=[]\;',./
</code>```

Want to replace all the special characters in this table variable like below

```<code>table1=123_____________________________
</code>```

How can I do that in Linux?

答:
Pipe it to sed and replace anything that is not ^ alphanumeric [:alnum:] with an underscore _.

```<code>sed 's/[^[:alnum:]]/_/g'
</code>```

In your code, this would look something like:

```<code>table1=$(echo table | sed 's/[^[:alnum:]]/_/g')
</code>```

Body:
I have a variable in Linux like below. This is not a valid variable I just created to test how to replace characters with some new characters.

table=123~!@#$%^&*()+|}{:"?><-=[]\;',./

Want to replace all the special characters in this table variable like below

table1=123_____________________________

How can I do that in Linux?

Body:
Pipe it to sed and replace anything that is not ^ alphanumeric [:alnum:] with an underscore _.

sed 's/[^[:alnum:]]/_/g'

In your code, this would look something like:

table1=$(echo table | sed 's/[^[:alnum:]]/_/g')


来源: stackexchange

问:
Adding a subelement to a subelement lxml
I am using lxml in an attempt to to output the following xml code:

```<code><annotation>
    <folder>images</folder>
    <filename>IMG_8111.JPG</filename>
    <size>
        <width>400</width>
        <height>400</height>
    </size>
    <segmented>0</segmented>
    <object>
        <name>Bottle</name>
        <bndbox>
            <xmin>16</xmin>
            <ymin>71</ymin>
            <xmax>390</xmax>
            <ymax>323</ymax>
        </bndbox>
    </object>
</annotation>
</code>```

Im using this tutorial to learn how to implement lxml for my needs. The issue I am facing is that my desired output has subelements to subelements. For instance - <annotation> is my main element, and then <folder>, <filename> and <size> are subelements, but then, <height> and <width>' are subelements to the` subelements. How do I make this happen with lxml. I have the following so far:

```<code>from lxml import etree
import xml.etree.cElementTree as ET

root = etree.Element("annotation")
etree.SubElement(root, "folder").text = "Child 1"
etree.SubElement(root, "filename").text = "Child 2"
size = etree.SubElement(root, "size").text = "Child 3"
etree.SubElement(size, "width").text = "Child 4"

with open ('xmltree.xml', 'wb') as f:
    f.write(etree.tostring(root, pretty_print = True))
</code>```

But it throws the following error:

```<code> etree.SubElement(size, "width").text = "Child 4"
TypeError: Argument '_parent' has incorrect type (expected lxml.etree._Element, got str)
</code>```

Please help me out on what I am doing wrong and how to proceed.

答:
In order for size = etree.SubElement(root, "size").text = "Child 3" to be evaluated as you expect it to be, it would have to be interpreted as:

```<code>(size = etree.SubElement(root, "size")).text = "Child 3"
</code>```

In Python, you can't perform an assignment in an expression. Instead, the way Python interprets this is:

```<code>size = "Child 3"
etree.SubElement(root, "size").text = "Child 3"
</code>```

You could rewrite your code using two separate lines to achieve your desired result:

```<code>size = etree.SubElement(root, "size")
size.text = "Child 3"
</code>```

After looking through the lxml API, it does not appear to be a way way to both create an element and assign a value to the text attribute in a single line.

ContentLicense: CC BY-SA 3.0

Body:
I am using lxml in an attempt to to output the following xml code:

<annotation>
    <folder>images</folder>
    <filename>IMG_8111.JPG</filename>
    <size>
        <width>400</width>
        <height>400</height>
    </size>
    <segmented>0</segmented>
    <object>
        <name>Bottle</name>
        <bndbox>
            <xmin>16</xmin>
            <ymin>71</ymin>
            <xmax>390</xmax>
            <ymax>323</ymax>
        </bndbox>
    </object>
</annotation>

Im using this tutorial to learn how to implement lxml for my needs. The issue I am facing is that my desired output has subelements to subelements. For instance - <annotation> is my main element, and then <folder>, <filename> and <size> are subelements, but then, <height> and <width>' are subelements to the` subelements. How do I make this happen with lxml. I have the following so far:

from lxml import etree
import xml.etree.cElementTree as ET

root = etree.Element("annotation")
etree.SubElement(root, "folder").text = "Child 1"
etree.SubElement(root, "filename").text = "Child 2"
size = etree.SubElement(root, "size").text = "Child 3"
etree.SubElement(size, "width").text = "Child 4"

with open ('xmltree.xml', 'wb') as f:
    f.write(etree.tostring(root, pretty_print = True))

But it throws the following error:

 etree.SubElement(size, "width").text = "Child 4"
TypeError: Argument '_parent' has incorrect type (expected lxml.etree._Element, got str)

Please help me out on what I am doing wrong and how to proceed.

Body:
In order for size = etree.SubElement(root, "size").text = "Child 3" to be evaluated as you expect it to be, it would have to be interpreted as:

(size = etree.SubElement(root, "size")).text = "Child 3"

In Python, you can't perform an assignment in an expression. Instead, the way Python interprets this is:

size = "Child 3"
etree.SubElement(root, "size").text = "Child 3"

You could rewrite your code using two separate lines to achieve your desired result:

size = etree.SubElement(root, "size")
size.text = "Child 3"

After looking through the lxml API, it does not appear to be a way way to both create an element and assign a value to the text attribute in a single line.


问:
Custom UIViewController transition doesn't next animations perform
When I use the custom UIViewControllerAnimatedTransitioning to do a custom transition from AViewController to BViewController it performs as expected, using a Cubic Animation, but then when I try to use a default iOS presentation, like a modal to transition from BViewController to CViewController, it doesn't animate at all.

Here's the code of the first transition:

```<code>class CubeTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    private var direction: Direction!

    convenience init(direction: Direction) {
        self.init()
        self.direction = direction
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 1
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        guard let fromView = transitionContext.view(forKey: .from),
              let toView = transitionContext.view(forKey: .to) else {
                return
        }
        toView.frame = fromView.frame

        containerView.backgroundColor = UIColor.white
        let fromViewIntialTransform = fromView.layer.transform

        fromView.layer.anchorPointZ = -((fromView.frame.size.width) / 2)
        var transform: CATransform3D = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (fromView.layer.anchorPointZ))
        fromView.layer.transform = transform
        containerView.addSubview(fromView)

        toView.alpha = 1
        fromView.alpha = 1

        let toViewIntialTransform = toView.layer.transform
        toView.layer.anchorPointZ = -((toView.frame.size.width) / 2)
        transform = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (toView.layer.anchorPointZ))
        toView.layer.transform = transform

        containerView.insertSubview(toView, belowSubview:fromView)

        // transform toView to it's begining position
        switch direction {
        case .left:                                      // t                      angle                  x  y  z
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 0, 1, 0)
        case .right:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
        case .up:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
        case .down:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
        default:
            break
        }

        UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: UIViewAnimationOptions(), animations: {

            // Animate toView to go to fromView initial position,
            // And the fromView to go to a new position
            switch self.direction {
            case .left:                                      // t                      angle                  x  y  z
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
            case .right:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
            case .up:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 1, 0, 0)
            case .down:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 1, 0, 0)
            default:
                break
            }
        }, completion: {(value: Bool) in
            fromView.layer.transform = fromViewIntialTransform
            toView.layer.transform = toViewIntialTransform
            fromView.layoutSubviews()
            toView.layoutSubviews()
            // This undo the transition if it's cancelled
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })

    }

}
</code>```

The thing gets even stranger when I use another transition to perform the segue from A to B, the transition from B to C starts to working again.

Second transition:

```<code>class PopTransition: NSObject, UIViewControllerAnimatedTransitioning {

    let duration = 0.3
    var originFrame = CGRect.zero
    var presenting = true

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let toView = transitionContext.view(forKey: .to)!
        let detailView = presenting ? toView : transitionContext.view(forKey: .from)!

        let initialFrame = presenting ? originFrame : detailView.frame
        let finalFrame = presenting ? detailView.frame : originFrame

        let xScaleFactor = presenting
            ? initialFrame.width / finalFrame.width
            : finalFrame.width / initialFrame.width

        let yScaleFactor = presenting
            ? initialFrame.height / finalFrame.height
            : finalFrame.height / initialFrame.height

        let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor)

        if presenting {
            detailView.transform = scaleTransform
            detailView.center = CGPoint(
                x: initialFrame.midX,
                y: initialFrame.midY)
        }

        containerView.addSubview(toView)
        containerView.bringSubview(toFront: detailView)

        UIView.animate(
            withDuration: duration,
            delay: 0.0,
            animations: {
                detailView.transform = self.presenting ? .identity : scaleTransform
                detailView.center = CGPoint(x: finalFrame.midX, y: finalFrame.midY)
        },
            completion:{_ in
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
        )
    }
}
</code>```

答:
You are modifying toView.layer.anchorPointZ and fromView.layer.anchorPointZ so when the transition from B to C is about to happen, the anchorPointZ is messed up.

Try saving and reseting it like you do with fromViewIntialTransform and toViewIntialTransform.

Body:
When I use the custom UIViewControllerAnimatedTransitioning to do a custom transition from AViewController to BViewController it performs as expected, using a Cubic Animation, but then when I try to use a default iOS presentation, like a modal to transition from BViewController to CViewController, it doesn't animate at all.

Here's the code of the first transition:

class CubeTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    private var direction: Direction!

    convenience init(direction: Direction) {
        self.init()
        self.direction = direction
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 1
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        guard let fromView = transitionContext.view(forKey: .from),
              let toView = transitionContext.view(forKey: .to) else {
                return
        }
        toView.frame = fromView.frame

        containerView.backgroundColor = UIColor.white
        let fromViewIntialTransform = fromView.layer.transform

        fromView.layer.anchorPointZ = -((fromView.frame.size.width) / 2)
        var transform: CATransform3D = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (fromView.layer.anchorPointZ))
        fromView.layer.transform = transform
        containerView.addSubview(fromView)

        toView.alpha = 1
        fromView.alpha = 1

        let toViewIntialTransform = toView.layer.transform
        toView.layer.anchorPointZ = -((toView.frame.size.width) / 2)
        transform = CATransform3DIdentity
        transform.m34 = -1.0 / 1000
        transform = CATransform3DTranslate(transform, 0, 0, (toView.layer.anchorPointZ))
        toView.layer.transform = transform

        containerView.insertSubview(toView, belowSubview:fromView)

        // transform toView to it's begining position
        switch direction {
        case .left:                                      // t                      angle                  x  y  z
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 0, 1, 0)
        case .right:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
        case .up:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
        case .down:
            toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
        default:
            break
        }

        UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: UIViewAnimationOptions(), animations: {

            // Animate toView to go to fromView initial position,
            // And the fromView to go to a new position
            switch self.direction {
            case .left:                                      // t                      angle                  x  y  z
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 0, 1, 0)
            case .right:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 0, 1, 0)
            case .up:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(Double.pi / 2), 1, 0, 0)
            case .down:
                toView.layer.transform = CATransform3DRotate((toView.layer.transform), CGFloat(-Double.pi/2), 1, 0, 0)
                fromView.layer.transform = CATransform3DRotate((fromView.layer.transform), CGFloat(-Double.pi / 2), 1, 0, 0)
            default:
                break
            }
        }, completion: {(value: Bool) in
            fromView.layer.transform = fromViewIntialTransform
            toView.layer.transform = toViewIntialTransform
            fromView.layoutSubviews()
            toView.layoutSubviews()
            // This undo the transition if it's cancelled
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })

    }

}

The thing gets even stranger when I use another transition to perform the segue from A to B, the transition from B to C starts to working again.

Second transition:

class PopTransition: NSObject, UIViewControllerAnimatedTransitioning {

    let duration = 0.3
    var originFrame = CGRect.zero
    var presenting = true

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let containerView = transitionContext.containerView
        let toView = transitionContext.view(forKey: .to)!
        let detailView = presenting ? toView : transitionContext.view(forKey: .from)!

        let initialFrame = presenting ? originFrame : detailView.frame
        let finalFrame = presenting ? detailView.frame : originFrame

        let xScaleFactor = presenting
            ? initialFrame.width / finalFrame.width
            : finalFrame.width / initialFrame.width

        let yScaleFactor = presenting
            ? initialFrame.height / finalFrame.height
            : finalFrame.height / initialFrame.height

        let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor)

        if presenting {
            detailView.transform = scaleTransform
            detailView.center = CGPoint(
                x: initialFrame.midX,
                y: initialFrame.midY)
        }

        containerView.addSubview(toView)
        containerView.bringSubview(toFront: detailView)

        UIView.animate(
            withDuration: duration,
            delay: 0.0,
            animations: {
                detailView.transform = self.presenting ? .identity : scaleTransform
                detailView.center = CGPoint(x: finalFrame.midX, y: finalFrame.midY)
        },
            completion:{_ in
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
        )
    }
}


问:
PHP MySQLi giving error with external connection but can connect from other sources
I'm migrating servers from a shared hosting server to a VPS. As part of the transition I want to have the site as it's currently running start using the database on the new server before I fully switch the site and DNS records over.

The new server has mysql up and running and I can connect both local from the server, and I can connect as an external connection using Sequal Pro app on my iMac. When I use the same details to connect in my PHP script though on the shared hosting server I get a (2002) Connection refusedDB: 0 error.

The PHP script looks like

```<code>$servername = "SERVERIP";
$usernamedb = "USERNAME";
$passworddb = "PASSWORD";
$dbname = "DBNAME";

$conn = new mysqli($servername, $usernamedb, $passworddb, $dbname, 3306);

if ($conn->connect_errno) {
    echo "Failed to connect to MySQL: (" . $conn->connect_errno . ") " . $conn->connect_error;
}
</code>```

I've checked /var/log/mysql/error.log and there isn't any issues being logged. It has to be something with the PHP connection rather than the VPS/MySQL side because I can connect from my home internet connection using Sequal Pro without issue so the server is definetly allowing connections from external sources using those username, password, and db name details.

I added the port number to the new mysqli statement in case the shared hosting had the default setup differently but it doesn't make a difference with or without it.

答:
From the comments, we know that it fails from the command line on the client box, but works from the command line (GUI, technically) on your personal box. We also know from these comments that it's not SELinux or IPTables. Thus, it must be either:

system/OS level setting on the client box other than SELinux or IPTables, or

router/firewall between your client box and the server.

Time to break out lower level (eg, IP) tools. Or, as you discovered, contact the upstream network administrator.

In the words of a Certain Famous Detective:

Once you eliminate the impossible, whatever remains, no matter how improbable, must be the truth.

Body:
I'm migrating servers from a shared hosting server to a VPS. As part of the transition I want to have the site as it's currently running start using the database on the new server before I fully switch the site and DNS records over.

The new server has mysql up and running and I can connect both local from the server, and I can connect as an external connection using Sequal Pro app on my iMac. When I use the same details to connect in my PHP script though on the shared hosting server I get a (2002) Connection refusedDB: 0 error.

The PHP script looks like

$servername = "SERVERIP";
$usernamedb = "USERNAME";
$passworddb = "PASSWORD";
$dbname = "DBNAME";

$conn = new mysqli($servername, $usernamedb, $passworddb, $dbname, 3306);

if ($conn->connect_errno) {
    echo "Failed to connect to MySQL: (" . $conn->connect_errno . ") " . $conn->connect_error;
}

I've checked /var/log/mysql/error.log and there isn't any issues being logged. It has to be something with the PHP connection rather than the VPS/MySQL side because I can connect from my home internet connection using Sequal Pro without issue so the server is definetly allowing connections from external sources using those username, password, and db name details.

I added the port number to the new mysqli statement in case the shared hosting had the default setup differently but it doesn't make a difference with or without it.


问:
unobtrusive validation not working with dynamic content
I'm having problems trying to get the unobtrusive jquery validation to work with a partial view that is loaded dynamically through an AJAX call.

I've been spending days trying to get this code to work with no luck.

Here's the View:

```<code>@model MvcApplication2.Models.test

@using (Html.BeginForm())
{
 @Html.ValidationSummary(true);
 <div id="res"></div>
 <input id="submit" type="submit" value="submit" />
}
</code>```

The Partial View:

```<code>@model MvcApplication2.Models.test

@Html.TextAreaFor(m => m.MyProperty);
@Html.ValidationMessageFor(m => m.MyProperty);

<script type="text/javascript" >
  $.validator.unobtrusive.parse(document);
</script>
</code>```

The Model:

```<code>  public class test
  {
    [Required(ErrorMessage= "required field")]
    public int MyProperty { get; set; }
  }
</code>```

The Controller:

```<code>    public ActionResult GetView()
    {
        return PartialView("Test");
    }
</code>```

and finally, the javascript:

```<code>$(doument).ready(function () {
$.ajax({
    url: '/test/getview',
    success: function (res) {

        $("#res").html(res);
        $.validator.unobtrusive.parse($("#res"));
    }
});

$("#submit").click(function () {
    if ($("form").valid()) {
        alert('valid');
        return true;
    } else {
        alert('not valid');
        return false;
    }
});
</code>```

The validation does not work. Even if I don't fill any information in the texbox, the submit event shows the alert ('valid').

However, if instead of loading dynamically the view, I use @Html.Partial("test", Model) to render the partial View in the main View (and I don't do the AJAX call), then the validation works just fine.

This is probably because if I load the content dynamically, the controls don't exist in the DOM yet. But I do a call to  $.validator.unobtrusive.parse($("#res"));  which should be enough to let the validator about the newly loaded controls...

Can anyone help ?

答: Surprisingly, when I viewed this question, the official ASP.NET docs still did not have any info about the unobtrusive parse() method or how to use it with dynamic content.  I took the liberty of creating an issue at the docs repo (referencing @Nadeem's original answer) and submitting a pull request to fix it.  This information is now visible in the client side validation section of the model validation topic.

Body:
I'm having problems trying to get the unobtrusive jquery validation to work with a partial view that is loaded dynamically through an AJAX call.

I've been spending days trying to get this code to work with no luck.

Here's the View:

@model MvcApplication2.Models.test

@using (Html.BeginForm())
{
 @Html.ValidationSummary(true);

 <input id="submit" type="submit" value="submit" />
}

The Partial View:

@model MvcApplication2.Models.test

@Html.TextAreaFor(m => m.MyProperty);
@Html.ValidationMessageFor(m => m.MyProperty);

The Model:

  public class test
  {
    [Required(ErrorMessage= "required field")]
    public int MyProperty { get; set; }
  }

The Controller:

    public ActionResult GetView()
    {
        return PartialView("Test");
    }

and finally, the javascript:

$(doument).ready(function () {
$.ajax({
    url: '/test/getview',
    success: function (res) {

        $("#res").html(res);
        $.validator.unobtrusive.parse($("#res"));
    }
});

$("#submit").click(function () {
    if ($("form").valid()) {
        alert('valid');
        return true;
    } else {
        alert('not valid');
        return false;
    }
});

The validation does not work. Even if I don't fill any information in the texbox, the submit event shows the alert ('valid').

However, if instead of loading dynamically the view, I use @Html.Partial("test", Model) to render the partial View in the main View (and I don't do the AJAX call), then the validation works just fine.

This is probably because if I load the content dynamically, the controls don't exist in the DOM yet. But I do a call to  $.validator.unobtrusive.parse($("#res"));  which should be enough to let the validator about the newly loaded controls...

Can anyone help ?


问:
C Program Crashing when Reallocing One Element Larger (2x)
I am a beginner to C and am trying to learn dynamic memory allocation in the simplest way - I have a program that manages student records and I have a few problems with it that I cannot for the life of me figure out even after hours and hours of googleing/stackoverflowing -- Here is what this program is to accomplish:

Take in student records

Add and Delete Records ( THESE ARE THE COMMANDS THAT DO NOT WORK)

Sort student records

Find a few extra values from these records

Here is what happens to create this error as found in GDB debugger (the problem comes with the addRecord function and the freeMemory function):

```<code>    *** Error in `/home/a.out': realloc(): invalid next size:
    0x0000000000c42060 ***
    Aborted
</code>```

And when compiled with GCC and ran outside of the GDB debugger it will just seg fault.

This only happens when I do these set of options in the program:

1) ADD A RECORD

2) DELETE A RECORD

3) ADD A RECORD ( THEN CRASHES )

or

1) ADD A RECORD

2) ADD A RECORD ( THEN CRASHES )

I'm not sure whats causing this and I have no idea how to fix it, can anyone help direct me in the right direction? I've tried adding a free after the realloc success in the freeMemory function but to no avail this then causes the program to crash upon deletion of an added record.

Here is the code:

```<code>    #include <stdio.h>
#include <stdlib.h>

// Declare functions:
void printMenu();
void printRecords(char** fn, char** ln, float* s);
void addRecord(char** fn, char** ln, float* s);
void deleteRecord(char** fn, char** ln, float* s);
int freeMemory(char** fn, char** ln, float* s, char* n, int matches);
int findName(char** ln,char* n);

static int records; // global records variable

int main(){
    int i, j;
    int choice;
    int option = -1;

    printf("WELCOME TO THE STUDENT RECORD MANAGER 100 V 1.0! \n");
    printf("Please indicate the number of student records you want to enter (min 5, max 15): \n");
    scanf("%d",&records);

    if(records < 5 || records > 15){
        printf("You must enter more than five and less than 15... terminating. \n");
        return 0;
    }

    // Declare arrays
    char** firstNames;
    char** lastNames;
    float* scores;

    // Declare variables
    char* search = malloc(64);

    firstNames  =   malloc(records*sizeof(*firstNames));
    lastNames   =   malloc(records*sizeof(*lastNames));
    scores      =   malloc(records*sizeof(float));

    printf("Please enter the records now (ex. firstName lastName score ENTER):\n");
    // Gather Records
    for(i = 0; i < records; i ++){
        printf("%d ",i+1);
        firstNames[i] = malloc(254 * sizeof(char));
        lastNames[i] = malloc(254 * sizeof(char));
        //scores[i] = malloc(sizeof(float));
        scanf("%s %s %f",firstNames[i], lastNames[i], &scores[i]);
    }

    // Generate menu and do actions
    do{
        printMenu();
        scanf("%d",&choice);

        switch(choice){
            case 1:
                printRecords(firstNames, lastNames, scores);
                break;
            case 2:
                addRecord(firstNames, lastNames, scores);
                break;
            case 3:
                deleteRecord(firstNames, lastNames, scores);
                break;
            case 0:
                return 0;
        }
    }
    while(1);
    return 0;
}

// Print user menu
void printMenu(){
    printf("\tMain Menu\t\n"
        "============================\n"
        " > Print records (press 1) \n"
        " > Add a new record (press 2) \n"
        " > Delete a record (press 3) \n"
        " > Exit the program (press 0)\n"
        "============================\n"
        "Please select an option: ");
}

// Print all user records
void printRecords(char** fn, char** ln, float* s){
    int i;
    printf("THERE ARE %d RECORDS \n",records);
    for(i=0;i<records;i++)
        printf("(%d) First name: %s | Last name: %s | Score: %0.2f \n",i,fn[i],ln[i],s[i]); // will start at the first item and go i amount in the index
}

// Add user record
void addRecord(char** fn, char**ln, float* s){
    char** tempPtr;
    float* tempFPtr;
    printf("Please input the values that you'd like to add (ex. firstName lastName score ENTER): \n");
    if(records+1 < 15){ // if the array is not larger than maximum value when we make it larger

        // lets reallocate the arrays
        tempPtr = realloc(fn, (records+1)*sizeof(*fn));
        if(tempPtr){
            printf("ALLOCATION successfully");
            fn = tempPtr;
        }
        else{
            printf("FAILED");
            // Realloc Failed
        }
        tempPtr = realloc(ln, (records+1)*sizeof(*ln));
        if(tempPtr){
            printf("ALLOCATION successfully");
            ln = tempPtr;
        }
        else{
            printf("FAILED");
            // Realloc Failed
        }
        /*tempFPtr = realloc(s, records+1*sizeof(float));
        if(tempFPtr){
            s = tempFPtr;
        }*/
        printf("There are now %d items.. \n", records);
        fn[records] = malloc(64); // in the LAST value of all arrays
        ln[records] = malloc(64);
        scanf("%s %s %f",fn[records], ln[records], &s[records]);
        printf("(%d) > ADDED -> First name: %s | Last name: %s | Score: %0.2f \n",records,fn[records],ln[records],s[records]);
        int i;
        records++; // increment by one
        printf("There are now %d items.. \n", records);
        printf(" > Record successfully added.\n");
    }
    else{
        printf(" > You have hit the max amount of records allowed for this program (15).\n");
    }

}

// Delete all instances of user record by (last Name)
void deleteRecord(char** fn, char**ln, float* s){
    char* lastName = malloc(32 * sizeof(char*));
    printf("What is the last name of the student you would like to delete? \n");
    scanf("%s", lastName);

    // searching for that record
    int matches = findName(ln, lastName);
    if(matches && records-matches > 4){ // this means it doesn't go below minimum 5
        if(freeMemory(fn, ln, s, lastName, matches)){
            printf(" > Record successfully deleted.\n");
            free(lastName);
        }
    }
    else{
        printf(" > Either no matches were found or deleting this value would put the number of records at less than 5. \n");
    }

}

// Extension of deleteRecord that does duplication to push 'delete' lastName to the end, then reallocates array to cut it off the end
int freeMemory(char** fn, char** ln, float* s, char* n, int matches){
    int i,j;

    /* LOGIC:
        - REALLOCATE ARRAY BY X LESS SIZE AFTER PUSHING THE VALUES TO BE REMOVED TO THE END
        - NEED TO DO THIS FOR THREE ARRAYS
        - TO REMOVE:
            - RUN THROUGH X AMOUNT OF TIMES PUSHING EACH SPECIFIC REMOVAL VALUE (IE) 1st found match
            - TO THE END
            SHIFT
                - FOUND 1st MATCH
                - MATCH = MATCH + 1
                - MATCH + ! = MATCH + 2
                - ETC UNTIL YOU HAVE A DUPLICATE AT THE END, THEN REALLOCATE BY 1 LESS
    */
    char** tempPtr = NULL;
    float* tempFPtr = NULL;
    for(i=0;i<matches;i++){ // gonna go through as many times as matches
        int match = 0;
        // let's make sure the name isn't on the end of the array before we do all this junk
        if(strcmp(n,*(ln+records-1)) == 0){
            printf("FN");
            tempPtr = realloc(fn, (records-1)*sizeof(*fn));
            if(tempPtr){
                fn = tempPtr;
                printf("FN PASSED");
                //free(fn[records]);
            }
            else{
                // Realloc Failed
                printf("FN FAILED");
            }
            printf("LN");
            tempPtr = realloc(ln, (records-1)*sizeof(*ln));
            if(tempPtr){
                ln = tempPtr;
                printf("LN PASSED");
                //free(ln[records]);
            }
            else{
                printf("LN FAILED");
                // Realloc Failed
            }

            records--;
        }
        else{
            // lets find the first match by going through each last name
            for(j=0;j<records-1;j++){
                // Lets find first match
                if(strcmp(n,ln[j]) == 0){ // accessing index
                    // lets start copying
                    *(ln+j) = *(ln+j+1);
                    *(fn+j) = *(fn+j+1);
                    *(s+j)  = *(s+j+1);
                    match = 1;
                }
                else if(match){
                    // already copied first val so lets start copying the rest until we get to the end.
                    *(ln+j) = *(ln+j+1);
                    *(fn+j) = *(fn+j+1);
                    *(s+j)  = *(s+j+1);
                }

            }
            printf("FN");
            tempPtr = realloc(fn, (records-1)*sizeof(*fn));
            if(tempPtr){
                fn = tempPtr;
                printf("FN PASSED");
                //free(fn[records]);
            }
            else{
                // Realloc Failed
                printf("FN FAILED");
            }
            printf("LN");
            tempPtr = realloc(ln, (records-1)*sizeof(*ln));
            if(tempPtr){
                ln = tempPtr;
                printf("LN PASSED");
                //free(ln[records]);
            }
            else{
                printf("LN FAILED");
                // Realloc Failed
            }

            /*tempFPtr = realloc(s, records-1*sizeof(float));
            if(tempFPtr){
                s = tempFPtr;
                printf("S PASSED");
            }
            else{
                printf("s FAILED ");
            }*/

            records--;
            match = 0;
        }
    }
    return 1;
}

// Finds how many instances of a last name are present
int findName(char** ln,char* n){
    int i, counter=0;

    for(i=0;i<records-1;i++){
        if(strcmp(n,*(ln+i)) == 0){
            counter++;
        }
    }
    return counter;
}
</code>```

答:
I have solved the problem. It was because I was not using triple pointers to it was not addressing the original variable.</p>

```<code>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void printMenu();
void printRecords(char** fn, char** ln, double* s);
void addRecord(char ***fn, char ***ln, double **s);
void addString(char ***strArray, char* str);
void addDouble(double** dubArray, double dub);
void deleteRecord(char*** fn, char*** ln, double** s);
void removeString(char ***strArray);
void removeDouble(double** dubArray);
int findName(char** ln,char* n);

int records;
int counter;

int main(){
    records = 0;
    counter = 1;

    int initRecords = 0;
    int choice,i;
    char **fn; // first Names
    char **ln; // last Names
    double *s; // score

    printf("=  =\n"
           "Please enter how many value"
           "s you would like to initall"
           "y enter [min 5, max 15]: ");
    scanf("%d", &initRecords);
    if(initRecords < 5 || initRecords > 15)
        return 0;

    // allocate memory
    fn = malloc(0); // will reallocate later
    ln = malloc(0);
    s =  malloc(0);

    printf("Please enter the value (firstName lastName score ENTER): \n");
    for(i = 0;i<(initRecords);i++){
        addRecord(&fn, &ln, &s);
        counter++;
    }

    printf("Records added... \n");
    do{
        printMenu();
        scanf("%d",&choice);
        switch(choice){
            case 1:
                printRecords(fn, ln, s);
                break;
            case 2:
                addRecord(&fn,&ln,&s);
                printf("> Record added. \n");
                break;
            case 3:
                deleteRecord(&fn, &ln, &s);
                printf("> Record deleted. \n");
                break;
            case 0:
                return 0;
            default:
                return 0;
        }
    }
    while(1);
}

// Print user menu
void printMenu(){
    printf("\tMain Menu\t\n"
        "============================\n"
        " > Print records (press 1) \n"
        " > Add a new record (press 2) \n"
        " > Delete a record (press 3) \n"
        "============================\n"
        "Please select an option: ");
}

// Print all user records
void printRecords(char** fn, char** ln, double* s){
    int i;
    for(i=0;i<records;i++)
        printf("(%d) First name: %s | Last name: %s | Score: %0.2lf \n",i+1,fn[i],ln[i],s[i]); // will start at the first item and go i amount in the index
}

void addRecord(char*** fn, char*** ln, double** s){
    // gather value

    char* fname = malloc(64);
    char* lname = malloc(64);
    double score;
    records++;

    printf("%d) ", (counter));
    scanf("%s %s %lf",fname, lname, &score);

    addString(fn, fname);
    addString(ln, fname);
    addDouble(s, score);
}

void addString(char*** strArray, char* str){
    // realloc array one larger
    *strArray = realloc(*strArray, (records) * sizeof(char*));

    // set pointer equal
    (*strArray)[records-1] = str;

}

void addDouble(double** dubArray, double dub){
    // realloc array one larger
    *dubArray = realloc(*dubArray, (records) * sizeof(double));

    // set pointer equal
    (*dubArray)[records-1] = dub;
}

void deleteRecord(char*** fn, char*** ln, double** s){
    //This part gets the name
    int i, j;
    char *name = malloc(64);
    printf("Please enter the last name of the record(s) you'd like to delete: ");
    scanf("%s",name);

    while(findName(*ln, name) != 0){
        for(i = 0;i<records && strcmp(name,(*ln)[i]) != 0;i++);
        records--;
        //free((*ln)[i]);
        //free((*fn)[i]);
        for(i=i; i < records-1; i++){
            (*ln)[i] = (*ln)[i+1];
            (*fn)[i] = (*fn)[i+1];
            (*s)[i] = (*s)[i+1];
        }
        removeString(fn);
        removeString(ln);
        removeDouble(s);
    }

}
void removeString(char ***strArray){
    *strArray = realloc(*strArray, (records) * sizeof(char*));

}
void removeDouble(double** dubArray){
    *dubArray = realloc(*dubArray, (records) * sizeof(double));
}

// Finds how many instances of a last name are present
int findName(char** ln,char* n){
    int i, counter=0;

    for(i=0;i<records-1;i++){
        if(strcmp(n,*(ln+i)) == 0){
            counter++;
        }
    }
    return counter;
}
</code>```

Body:
I am a beginner to C and am trying to learn dynamic memory allocation in the simplest way - I have a program that manages student records and I have a few problems with it that I cannot for the life of me figure out even after hours and hours of googleing/stackoverflowing -- Here is what this program is to accomplish:

Take in student records

Add and Delete Records ( THESE ARE THE COMMANDS THAT DO NOT WORK)

Sort student records

Find a few extra values from these records

Here is what happens to create this error as found in GDB debugger (the problem comes with the addRecord function and the freeMemory function):

    *** Error in `/home/a.out': realloc(): invalid next size:
    0x0000000000c42060 ***
    Aborted

And when compiled with GCC and ran outside of the GDB debugger it will just seg fault.

This only happens when I do these set of options in the program:

1) ADD A RECORD

2) DELETE A RECORD

3) ADD A RECORD ( THEN CRASHES )

or

1) ADD A RECORD

2) ADD A RECORD ( THEN CRASHES )

I'm not sure whats causing this and I have no idea how to fix it, can anyone help direct me in the right direction? I've tried adding a free after the realloc success in the freeMemory function but to no avail this then causes the program to crash upon deletion of an added record.

Here is the code:

    #include <stdio.h>
#include <stdlib.h>

// Declare functions:
void printMenu();
void printRecords(char** fn, char** ln, float* s);
void addRecord(char** fn, char** ln, float* s);
void deleteRecord(char** fn, char** ln, float* s);
int freeMemory(char** fn, char** ln, float* s, char* n, int matches);
int findName(char** ln,char* n);

static int records; // global records variable

int main(){
    int i, j;
    int choice;
    int option = -1;

    printf("WELCOME TO THE STUDENT RECORD MANAGER 100 V 1.0! \n");
    printf("Please indicate the number of student records you want to enter (min 5, max 15): \n");
    scanf("%d",&records);

    if(records < 5 || records > 15){
        printf("You must enter more than five and less than 15... terminating. \n");
        return 0;
    }

    // Declare arrays
    char** firstNames;
    char** lastNames;
    float* scores;

    // Declare variables
    char* search = malloc(64);

    firstNames  =   malloc(records*sizeof(*firstNames));
    lastNames   =   malloc(records*sizeof(*lastNames));
    scores      =   malloc(records*sizeof(float));

    printf("Please enter the records now (ex. firstName lastName score ENTER):\n");
    // Gather Records
    for(i = 0; i < records; i ++){
        printf("%d ",i+1);
        firstNames[i] = malloc(254 * sizeof(char));
        lastNames[i] = malloc(254 * sizeof(char));
        //scores[i] = malloc(sizeof(float));
        scanf("%s %s %f",firstNames[i], lastNames[i], &scores[i]);
    }

    // Generate menu and do actions
    do{
        printMenu();
        scanf("%d",&choice);

        switch(choice){
            case 1:
                printRecords(firstNames, lastNames, scores);
                break;
            case 2:
                addRecord(firstNames, lastNames, scores);
                break;
            case 3:
                deleteRecord(firstNames, lastNames, scores);
                break;
            case 0:
                return 0;
        }
    }
    while(1);
    return 0;
}

// Print user menu
void printMenu(){
    printf("\tMain Menu\t\n"
        "============================\n"
        " > Print records (press 1) \n"
        " > Add a new record (press 2) \n"
        " > Delete a record (press 3) \n"
        " > Exit the program (press 0)\n"
        "============================\n"
        "Please select an option: ");
}

// Print all user records
void printRecords(char** fn, char** ln, float* s){
    int i;
    printf("THERE ARE %d RECORDS \n",records);
    for(i=0;i<records;i++)
        printf("(%d) First name: %s | Last name: %s | Score: %0.2f \n",i,fn[i],ln[i],s[i]); // will start at the first item and go i amount in the index
}

// Add user record
void addRecord(char** fn, char**ln, float* s){
    char** tempPtr;
    float* tempFPtr;
    printf("Please input the values that you'd like to add (ex. firstName lastName score ENTER): \n");
    if(records+1 < 15){ // if the array is not larger than maximum value when we make it larger

        // lets reallocate the arrays
        tempPtr = realloc(fn, (records+1)*sizeof(*fn));
        if(tempPtr){
            printf("ALLOCATION successfully");
            fn = tempPtr;
        }
        else{
            printf("FAILED");
            // Realloc Failed
        }
        tempPtr = realloc(ln, (records+1)*sizeof(*ln));
        if(tempPtr){
            printf("ALLOCATION successfully");
            ln = tempPtr;
        }
        else{
            printf("FAILED");
            // Realloc Failed
        }
        /*tempFPtr = realloc(s, records+1*sizeof(float));
        if(tempFPtr){
            s = tempFPtr;
        }*/
        printf("There are now %d items.. \n", records);
        fn[records] = malloc(64); // in the LAST value of all arrays
        ln[records] = malloc(64);
        scanf("%s %s %f",fn[records], ln[records], &s[records]);
        printf("(%d) > ADDED -> First name: %s | Last name: %s | Score: %0.2f \n",records,fn[records],ln[records],s[records]);
        int i;
        records++; // increment by one
        printf("There are now %d items.. \n", records);
        printf(" > Record successfully added.\n");
    }
    else{
        printf(" > You have hit the max amount of records allowed for this program (15).\n");
    }

}

// Delete all instances of user record by (last Name)
void deleteRecord(char** fn, char**ln, float* s){
    char* lastName = malloc(32 * sizeof(char*));
    printf("What is the last name of the student you would like to delete? \n");
    scanf("%s", lastName);

    // searching for that record
    int matches = findName(ln, lastName);
    if(matches && records-matches > 4){ // this means it doesn't go below minimum 5
        if(freeMemory(fn, ln, s, lastName, matches)){
            printf(" > Record successfully deleted.\n");
            free(lastName);
        }
    }
    else{
        printf(" > Either no matches were found or deleting this value would put the number of records at less than 5. \n");
    }

}

// Extension of deleteRecord that does duplication to push 'delete' lastName to the end, then reallocates array to cut it off the end
int freeMemory(char** fn, char** ln, float* s, char* n, int matches){
    int i,j;

    /* LOGIC:
        - REALLOCATE ARRAY BY X LESS SIZE AFTER PUSHING THE VALUES TO BE REMOVED TO THE END
        - NEED TO DO THIS FOR THREE ARRAYS
        - TO REMOVE:
            - RUN THROUGH X AMOUNT OF TIMES PUSHING EACH SPECIFIC REMOVAL VALUE (IE) 1st found match
            - TO THE END
            SHIFT
                - FOUND 1st MATCH
                - MATCH = MATCH + 1
                - MATCH + ! = MATCH + 2
                - ETC UNTIL YOU HAVE A DUPLICATE AT THE END, THEN REALLOCATE BY 1 LESS
    */
    char** tempPtr = NULL;
    float* tempFPtr = NULL;
    for(i=0;i<matches;i++){ // gonna go through as many times as matches
        int match = 0;
        // let's make sure the name isn't on the end of the array before we do all this junk
        if(strcmp(n,*(ln+records-1)) == 0){
            printf("FN");
            tempPtr = realloc(fn, (records-1)*sizeof(*fn));
            if(tempPtr){
                fn = tempPtr;
                printf("FN PASSED");
                //free(fn[records]);
            }
            else{
                // Realloc Failed
                printf("FN FAILED");
            }
            printf("LN");
            tempPtr = realloc(ln, (records-1)*sizeof(*ln));
            if(tempPtr){
                ln = tempPtr;
                printf("LN PASSED");
                //free(ln[records]);
            }
            else{
                printf("LN FAILED");
                // Realloc Failed
            }

            records--;
        }
        else{
            // lets find the first match by going through each last name
            for(j=0;j<records-1;j++){
                // Lets find first match
                if(strcmp(n,ln[j]) == 0){ // accessing index
                    // lets start copying
                    *(ln+j) = *(ln+j+1);
                    *(fn+j) = *(fn+j+1);
                    *(s+j)  = *(s+j+1);
                    match = 1;
                }
                else if(match){
                    // already copied first val so lets start copying the rest until we get to the end.
                    *(ln+j) = *(ln+j+1);
                    *(fn+j) = *(fn+j+1);
                    *(s+j)  = *(s+j+1);
                }

            }
            printf("FN");
            tempPtr = realloc(fn, (records-1)*sizeof(*fn));
            if(tempPtr){
                fn = tempPtr;
                printf("FN PASSED");
                //free(fn[records]);
            }
            else{
                // Realloc Failed
                printf("FN FAILED");
            }
            printf("LN");
            tempPtr = realloc(ln, (records-1)*sizeof(*ln));
            if(tempPtr){
                ln = tempPtr;
                printf("LN PASSED");
                //free(ln[records]);
            }
            else{
                printf("LN FAILED");
                // Realloc Failed
            }

            /*tempFPtr = realloc(s, records-1*sizeof(float));
            if(tempFPtr){
                s = tempFPtr;
                printf("S PASSED");
            }
            else{
                printf("s FAILED ");
            }*/

            records--;
            match = 0;
        }
    }
    return 1;
}

// Finds how many instances of a last name are present
int findName(char** ln,char* n){
    int i, counter=0;

    for(i=0;i<records-1;i++){
        if(strcmp(n,*(ln+i)) == 0){
            counter++;
        }
    }
    return counter;
}

Body:
I have solved the problem. It was because I was not using triple pointers to it was not addressing the original variable.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void printMenu();
void printRecords(char** fn, char** ln, double* s);
void addRecord(char ***fn, char ***ln, double **s);
void addString(char ***strArray, char* str);
void addDouble(double** dubArray, double dub);
void deleteRecord(char*** fn, char*** ln, double** s);
void removeString(char ***strArray);
void removeDouble(double** dubArray);
int findName(char** ln,char* n);

int records;
int counter;

int main(){
    records = 0;
    counter = 1;

    int initRecords = 0;
    int choice,i;
    char **fn; // first Names
    char **ln; // last Names
    double *s; // score

    printf("=  =\n"
           "Please enter how many value"
           "s you would like to initall"
           "y enter [min 5, max 15]: ");
    scanf("%d", &initRecords);
    if(initRecords < 5 || initRecords > 15)
        return 0;

    // allocate memory
    fn = malloc(0); // will reallocate later
    ln = malloc(0);
    s =  malloc(0);

    printf("Please enter the value (firstName lastName score ENTER): \n");
    for(i = 0;i<(initRecords);i++){
        addRecord(&fn, &ln, &s);
        counter++;
    }

    printf("Records added... \n");
    do{
        printMenu();
        scanf("%d",&choice);
        switch(choice){
            case 1:
                printRecords(fn, ln, s);
                break;
            case 2:
                addRecord(&fn,&ln,&s);
                printf("> Record added. \n");
                break;
            case 3:
                deleteRecord(&fn, &ln, &s);
                printf("> Record deleted. \n");
                break;
            case 0:
                return 0;
            default:
                return 0;
        }
    }
    while(1);
}

// Print user menu
void printMenu(){
    printf("\tMain Menu\t\n"
        "============================\n"
        " > Print records (press 1) \n"
        " > Add a new record (press 2) \n"
        " > Delete a record (press 3) \n"
        "============================\n"
        "Please select an option: ");
}

// Print all user records
void printRecords(char** fn, char** ln, double* s){
    int i;
    for(i=0;i<records;i++)
        printf("(%d) First name: %s | Last name: %s | Score: %0.2lf \n",i+1,fn[i],ln[i],s[i]); // will start at the first item and go i amount in the index
}

void addRecord(char*** fn, char*** ln, double** s){
    // gather value

    char* fname = malloc(64);
    char* lname = malloc(64);
    double score;
    records++;

    printf("%d) ", (counter));
    scanf("%s %s %lf",fname, lname, &score);

    addString(fn, fname);
    addString(ln, fname);
    addDouble(s, score);
}

void addString(char*** strArray, char* str){
    // realloc array one larger
    *strArray = realloc(*strArray, (records) * sizeof(char*));

    // set pointer equal
    (*strArray)[records-1] = str;

}

void addDouble(double** dubArray, double dub){
    // realloc array one larger
    *dubArray = realloc(*dubArray, (records) * sizeof(double));

    // set pointer equal
    (*dubArray)[records-1] = dub;
}

void deleteRecord(char*** fn, char*** ln, double** s){
    //This part gets the name
    int i, j;
    char *name = malloc(64);
    printf("Please enter the last name of the record(s) you'd like to delete: ");
    scanf("%s",name);

    while(findName(*ln, name) != 0){
        for(i = 0;i<records && strcmp(name,(*ln)[i]) != 0;i++);
        records--;
        //free((*ln)[i]);
        //free((*fn)[i]);
        for(i=i; i < records-1; i++){
            (*ln)[i] = (*ln)[i+1];
            (*fn)[i] = (*fn)[i+1];
            (*s)[i] = (*s)[i+1];
        }
        removeString(fn);
        removeString(ln);
        removeDouble(s);
    }

}
void removeString(char ***strArray){
    *strArray = realloc(*strArray, (records) * sizeof(char*));

}
void removeDouble(double** dubArray){
    *dubArray = realloc(*dubArray, (records) * sizeof(double));
}

// Finds how many instances of a last name are present
int findName(char** ln,char* n){
    int i, counter=0;

    for(i=0;i<records-1;i++){
        if(strcmp(n,*(ln+i)) == 0){
            counter++;
        }
    }
    return counter;
}


问:
Unable to compare Array element to String using InStr
I'm using VB6 and I'm trying to compare a string to an Array element. I know that if the string exists it will always be in index 0. Currently it always skips to End If. What am I doing wrong?

```<code>Dim attributeFinal As String,
strArray() As String,
stringFound As Integer,
code As String

attributes = "Material=10011,C=123123"

strArray = Split(attributes, ",")
If UBound(strArray) Then
    code = strArray(0)
    stringFound = InStr(1, "Material", code)
    If stringFound <> 0 Then
        attributeFinal = code & ",C=" & cCode
    End If
End If
</code>```

答:
Solved thanks to @AndrewMorton. The arguments for comparing strings were in reverse order. </p>

```<code>Dim attributeFinal As String,
strArray() As String,
stringFound As Integer,
code As String

attributes = "Material=10011,C=123123"

strArray = Split(attributes, ",")
If UBound(strArray) Then
    code = strArray(0)
    stringFound = InStr(code, "Material")
    If stringFound <> 0 Then
        attributeFinal = code & ",C=" & cCode
    End If
End If
</code>```

Body:
I'm using VB6 and I'm trying to compare a string to an Array element. I know that if the string exists it will always be in index 0. Currently it always skips to End If. What am I doing wrong?

Dim attributeFinal As String,
strArray() As String,
stringFound As Integer,
code As String

attributes = "Material=10011,C=123123"

strArray = Split(attributes, ",")
If UBound(strArray) Then
    code = strArray(0)
    stringFound = InStr(1, "Material", code)
    If stringFound <> 0 Then
        attributeFinal = code & ",C=" & cCode
    End If
End If

Body:
Solved thanks to @AndrewMorton. The arguments for comparing strings were in reverse order.

Dim attributeFinal As String,
strArray() As String,
stringFound As Integer,
code As String

attributes = "Material=10011,C=123123"

strArray = Split(attributes, ",")
If UBound(strArray) Then
    code = strArray(0)
    stringFound = InStr(code, "Material")
    If stringFound <> 0 Then
        attributeFinal = code & ",C=" & cCode
    End If
End If


问:
php remove from array if property value is in another array
I want to remove all elements from arr2 that have a type contained in arr1:

```<code>    arr1 = ['A', 'B', 'C']

    arr2 = [
        [
        'name' => 'jane',
        'type' => 'X'
        ],
        [
        'name' => 'jon',
        'type' => 'B'
        ]
    ]
</code>```

So jon should be removed. Is there some built in function like array_diff?

答:
I don't think there's a way to do it with just one built-in array function, but you can combine some of them to do it.</p>

```<code>$record_types = array_column($arr2, 'type');

$records_to_keep = array_diff($record_types, $arr1);

$result = array_intersect_key($arr2, $records_to_keep);
</code>```

Body:
I want to remove all elements from arr2 that have a type contained in arr1:

    arr1 = ['A', 'B', 'C']

    arr2 = [
        [
        'name' => 'jane',
        'type' => 'X'
        ],
        [
        'name' => 'jon',
        'type' => 'B'
        ]
    ]

So jon should be removed. Is there some built in function like array_diff?

Body:
I don't think there's a way to do it with just one built-in array function, but you can combine some of them to do it.

$record_types = array_column($arr2, 'type');

$records_to_keep = array_diff($record_types, $arr1);

$result = array_intersect_key($arr2, $records_to_keep);


问:
python : COMERROR when reading file
I'm using Windows and Jupyter to write python code, and when I'm using package comtypes.client, it is unstable, sometimes it works, sometimes it doesn't. What I'm doing is trying to convert pptx file to pdf file. Here is my code :

```<code>import comtypes.client

def PPTtoPDF(inputFileName, outputFileName, formatType = 32):
    powerpoint = comtypes.client.CreateObject("Powerpoint.Application")
    powerpoint.Visible = 1

    if outputFileName[-3:] != 'pdf':
        outputFileName = outputFileName + ".pdf"
    deck = powerpoint.Presentations.Open(inputFileName)
    deck.SaveAs(outputFileName, formatType) # formatType = 32 for ppt to pdf
    deck.Close()
    powerpoint.Quit()

PPTtoPDF('07-20 contact PPT.pptx','./Reports/07-20 contact result',32)
</code>```

And the error is:

```<code>COMError: (-2147024894, 'The system cannot find the file specified.', (None, None, None, 0, None))
</code>```

I don't think there's something wrong with this code, since it works well for several times, so maybe it is because of the computer environment or something else. Could any one tell me how I can make this code stable, or is there any better to convert PPTX to PDF in python?

Thank you all~

答:
I received the same error and I have a 64-bit Windows PC. My solution involved specifying the file path with:</p>

```<code># Open the ppt file path. sys.argv[1] is the ppt name.
mypath = os.path.abspath(__file__)
mydir = os.path.dirname(mypath)
file_input = os.path.join(mydir, sys.argv[1])

# create the pdf output file path and call your function
file_output = os.path.join(mydir, sys.argv[1][:-4] + "pdf")
PPTtoPDF(file_input, file_output)
</code>```

Title: python : COMERROR when reading file

Body:
I'm using Windows and Jupyter to write python code, and when I'm using package comtypes.client, it is unstable, sometimes it works, sometimes it doesn't. What I'm doing is trying to convert pptx file to pdf file. Here is my code :

import comtypes.client

def PPTtoPDF(inputFileName, outputFileName, formatType = 32):
    powerpoint = comtypes.client.CreateObject("Powerpoint.Application")
    powerpoint.Visible = 1

    if outputFileName[-3:] != 'pdf':
        outputFileName = outputFileName + ".pdf"
    deck = powerpoint.Presentations.Open(inputFileName)
    deck.SaveAs(outputFileName, formatType) # formatType = 32 for ppt to pdf
    deck.Close()
    powerpoint.Quit()

PPTtoPDF('07-20 contact PPT.pptx','./Reports/07-20 contact result',32)

And the error is:

COMError: (-2147024894, 'The system cannot find the file specified.', (None, None, None, 0, None))

I don't think there's something wrong with this code, since it works well for several times, so maybe it is because of the computer environment or something else. Could any one tell me how I can make this code stable, or is there any better to convert PPTX to PDF in python?

Thank you all~

Body:
I received the same error and I have a 64-bit Windows PC. My solution involved specifying the file path with:

# Open the ppt file path. sys.argv[1] is the ppt name.
mypath = os.path.abspath(__file__)
mydir = os.path.dirname(mypath)
file_input = os.path.join(mydir, sys.argv[1])

# create the pdf output file path and call your function
file_output = os.path.join(mydir, sys.argv[1][:-4] + "pdf")
PPTtoPDF(file_input, file_output)


问:
MSSQL select customers with same products
Hello I would like to SELECT the name of the customer who ordered this set of products like the Brazilian customers from Northwind database. I did brazilian products here:

```<code>select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil'
</code>```

but what now? How I can find them? I tried to do:

```<code>select [CompanyName], [ProductName]
from [dbo].[Customers] join [dbo].[Orders] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
join [dbo].[Order Details] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Products] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
where  [ProductName] in  (
select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil')
</code>```

but this also doesn't work :/

答:
Since CompanyName is on the Customer table in your original query, just select it from there.</p>

```<code>select
    [CompanyName]
  , [ProductName]
from
    [dbo].[Products]
    join
        [dbo].[Order Details]
        on
            [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
    join
        [dbo].[Orders]
        on
            [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
    join
        [dbo].[Customers]
        on
            [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where
    [Country] = 'Brazil'
</code>```

Body:
Hello I would like to SELECT the name of the customer who ordered this set of products like the Brazilian customers from Northwind database. I did brazilian products here:

select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil'

but what now? How I can find them? I tried to do:

select [CompanyName], [ProductName]
from [dbo].[Customers] join [dbo].[Orders] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
join [dbo].[Order Details] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Products] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
where  [ProductName] in  (
select [ProductName]
from [dbo].[Products] join [dbo].[Order Details] on [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
join [dbo].[Orders] on [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
join [dbo].[Customers] on [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where [Country] = 'Brazil')

but this also doesn't work :/

Body:
Since CompanyName is on the Customer table in your original query, just select it from there.

select
    [CompanyName]
  , [ProductName]
from
    [dbo].[Products]
    join
        [dbo].[Order Details]
        on
            [dbo].[Products].ProductID = [dbo].[Order Details].ProductID
    join
        [dbo].[Orders]
        on
            [dbo].[Order Details].OrderID = [dbo].[Orders].OrderID
    join
        [dbo].[Customers]
        on
            [dbo].[Orders].CustomerID = [dbo].[Customers].CustomerID
where
    [Country] = 'Brazil'


问:
In Ruby, is there a way to remove only 1 match in an Array easily?
In Ruby, the array subtraction or reject

```<code>>> [1,3,5,7,7] - [7]
=> [1, 3, 5]

>> [1,3,5,7,7].reject{|i| i == 7}
=> [1, 3, 5]
</code>```

will remove all entries in the array.  Is there an easy to remove just 1 occurrence?

ContentLicense: CC BY-SA 2.5

Body:
In Ruby, the array subtraction or reject

>> [1,3,5,7,7] - [7]
=> [1, 3, 5]

>> [1,3,5,7,7].reject{|i| i == 7}
=> [1, 3, 5]

will remove all entries in the array.  Is there an easy to remove just 1 occurrence?

Body:
>> a = [1,3,5,7,7]

>> a.slice!(a.index(7))
=> 7

>> a
=> [1,3,5,7]


问:
Group repeated elements of a list
I am trying to create a function that receives a list and return another list with the repeated elements.

For example for the input A = [2,2,1,1,3,2] (the list is not sorted) and the function would return result = [[1,1], [2,2,2]]. The result doesn't need to be sorted.

I already did it in Wolfram Mathematica but now I have to translate it to python3, Mathematica has some functions like Select, Map and Split that makes it very simple without using long loops with a lot of instructions.

答:
This is a job for Counter(). Iterating over each element, x, and checking A.count(x) has a O(N^2) complexity. Counter() will count how many times each element exists in your iterable in one pass and then you can generate your result by iterating over that dictionary.

```<code>>>> from collections import Counter
>>> A = [2,2,1,1,3,2]
>>> counts = Counter(A)
>>> result = [[key] * value for key, value in counts.items() if value > 1]
>>> result
[[2, 2, 2], [[1, 1]]
</code>```

Title: Group repeated elements of a list

Body:
This is a job for Counter(). Iterating over each element, x, and checking A.count(x) has a O(N^2) complexity. Counter() will count how many times each element exists in your iterable in one pass and then you can generate your result by iterating over that dictionary.

>>> from collections import Counter
>>> A = [2,2,1,1,3,2]
>>> counts = Counter(A)
>>> result = [[key] * value for key, value in counts.items() if value > 1]
>>> result
[[2, 2, 2], [[1, 1]]


问:
Split string into multiple alpha and numeric segments
I have a string like "ABCD232ERE44RR". How can I split it into separate segments by letters/numbers. I need:
Segment1: ABCD
Segment2: 232
Segment3: ERE
Segment4: 44

There could be any number of segments. I am thinking go Regex but don't understand how to write it properly

答:
If you decide not to use regex, you can always go the manual route.</p>

```<code>const string str = "ABCD232ERE44RR1SGGSG3333GSDGSDG";

var result = new List<StringBuilder>
{
    new StringBuilder()
};

char last = str[0];

result.Last().Append(last);

bool isLastNum = Char.IsNumber(last);

for (int i = 1; i < str.Length; i++)
{
    char ch = str[i];

    if (!((Char.IsDigit(ch) && isLastNum) || (Char.IsLetter(ch) && !isLastNum)))
    {
        result.Add(new StringBuilder());
    }

    result.Last().Append(ch);
    last = ch;
    isLastNum = Char.IsDigit(ch);
}
</code>```

Body:
If you decide not to use regex, you can always go the manual route.

const string str = "ABCD232ERE44RR1SGGSG3333GSDGSDG";

var result = new List<StringBuilder>
{
    new StringBuilder()
};

char last = str[0];

result.Last().Append(last);

bool isLastNum = Char.IsNumber(last);

for (int i = 1; i < str.Length; i++)
{
    char ch = str[i];

    if (!((Char.IsDigit(ch) && isLastNum) || (Char.IsLetter(ch) && !isLastNum)))
    {
        result.Add(new StringBuilder());
    }

    result.Last().Append(ch);
    last = ch;
    isLastNum = Char.IsDigit(ch);
}


问:
XSLT Newbie - Looping and Matching Elements
Brand new to XSLT but managed to hack my way through to extract the data I needed...

I'm now stuck on extracting the data into a required format to upload into a database...  I need to match each PGBLK with its corresponding TASK (please see example below).

Pretty sure I want to use XSLT Looping but to be honest I'm not sure, any assistance would be greatly appreciated!

Here's the source XML:

```<code><?xml version="1.0" encoding="UTF-8"?>
 <PGBLK CHAPNBR="05" CHG="U" CONFNBR="0" PGBLKNBR="2" REVDATE="20160608" SECTNBR="00" SUBJNBR="00">
  <TASK CHAPNBR="05" CHG="R" FUNC="912" PGBLKNBR="2" REVDATE="20160520" SECTNBR="00" SEQ="001"
    SUBJNBR="00"/>
    <EFFECT EFFRG="000" EFFTEXT="ALL"/>
  <TASK CHAPNBR="05" CHG="R" FUNC="910" PGBLKNBR="2" REVDATE="20160520" SECTNBR="00" SEQ="801"
    SUBJNBR="00">
    <EFFECT EFFRG="000" EFFTEXT="ALL"/>
   </TASK>
</PGBLK>
</code>```

Current XSLT:

```<code><xsl:template match="RTM">

 <REFERENCES>
    <xsl:attribute name="DATE">
        <xsl:value-of select="current-date()"/>
    </xsl:attribute>
        <xsl:for-each select="//PGBLK">
            <REF>
             <PGBLK>
              <xsl:value-of select="concat(@CHAPNBR, '-', @SECTNBR, '-', @SUBJNBR, '-', @PGBLKNBR, '-0')"/>
                </PGBLK>
            <TASK>
             <xsl:value-of select="TASK/concat(@CHAPNBR, '-', @SECTNBR, '-', @SUBJNBR, '-', @FUNC, '-', @SEQ, ',')"/>
            </TASK>
            </REF>
        </xsl:for-each>
    </REFERENCES>
</xsl:template>
</code>```

Current XML Output:

```<code><REFERENCES DATE="2017-11-15-06:00">
 <REF>
  <PGBLK>05-00-00-2-0</PGBLK>
  <TASK>05-00-00-912-001, 05-00-00-910-801,</TASK>
 </REF>
</REFERENCES>
</code>```

Desired XML Output:

```<code><REFERENCES DATE="2017-11-15-06:00">
 <REF>
  <PGBLK>05-00-00-2-0</PGBLK><TASK>05-00-00-912-001</TASK>
  <PGBLK>05-00-00-2-0</PGBLK><TASK>05-00-00-910-801</TASK>
 </REF>
</REFERENCES>
</code>```

答:
If you want to map PGBLK to REF and then each TASK to a pair of PGBLK and TASK then the following should help:

```<code><?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="RTM">
    <REFERENCES DATA="{current-date()}">
        <xsl:apply-templates/>
    </REFERENCES>
</xsl:template>

<xsl:template match="PGBLK">
    <REF>
        <xsl:apply-templates select="TASK"/>
    </REF>
</xsl:template>

<xsl:template match="TASK">
    <PGBLK>
        <xsl:value-of select="../((@CHAPNBR, @SECTNBR, @SUBJNBR, @PGBLKNBR)/string(), '0')" separator="-"/>
    </PGBLK>
    <xsl:copy>
        <xsl:value-of select="@CHAPNBR, @SECTNBR, @SUBJNBR, @FUNC, @SEQ" separator="-"/>
    </xsl:copy>
</xsl:template>

</xsl:transform>
</code>```

http://xsltransform.net/ehVYZP2

Body:
Brand new to XSLT but managed to hack my way through to extract the data I needed...

I'm now stuck on extracting the data into a required format to upload into a database...  I need to match each PGBLK with its corresponding TASK (please see example below).

Pretty sure I want to use XSLT Looping but to be honest I'm not sure, any assistance would be greatly appreciated!

Here's the source XML:

<?xml version="1.0" encoding="UTF-8"?>
 <PGBLK CHAPNBR="05" CHG="U" CONFNBR="0" PGBLKNBR="2" REVDATE="20160608" SECTNBR="00" SUBJNBR="00">
  <TASK CHAPNBR="05" CHG="R" FUNC="912" PGBLKNBR="2" REVDATE="20160520" SECTNBR="00" SEQ="001"
    SUBJNBR="00"/>
    <EFFECT EFFRG="000" EFFTEXT="ALL"/>
  <TASK CHAPNBR="05" CHG="R" FUNC="910" PGBLKNBR="2" REVDATE="20160520" SECTNBR="00" SEQ="801"
    SUBJNBR="00">
    <EFFECT EFFRG="000" EFFTEXT="ALL"/>
   </TASK>
</PGBLK>

Current XSLT:

<xsl:template match="RTM">

 <REFERENCES>
    <xsl:attribute name="DATE">
        <xsl:value-of select="current-date()"/>
    </xsl:attribute>
        <xsl:for-each select="//PGBLK">
            <REF>
             <PGBLK>
              <xsl:value-of select="concat(@CHAPNBR, '-', @SECTNBR, '-', @SUBJNBR, '-', @PGBLKNBR, '-0')"/>
                </PGBLK>
            <TASK>
             <xsl:value-of select="TASK/concat(@CHAPNBR, '-', @SECTNBR, '-', @SUBJNBR, '-', @FUNC, '-', @SEQ, ',')"/>
            </TASK>
            </REF>
        </xsl:for-each>
    </REFERENCES>
</xsl:template>

Current XML Output:

<REFERENCES DATE="2017-11-15-06:00">
 <REF>
  <PGBLK>05-00-00-2-0</PGBLK>
  <TASK>05-00-00-912-001, 05-00-00-910-801,</TASK>
 </REF>
</REFERENCES>

Desired XML Output:

<REFERENCES DATE="2017-11-15-06:00">
 <REF>
  <PGBLK>05-00-00-2-0</PGBLK><TASK>05-00-00-912-001</TASK>
  <PGBLK>05-00-00-2-0</PGBLK><TASK>05-00-00-910-801</TASK>
 </REF>
</REFERENCES>

Body:
If you want to map PGBLK to REF and then each TASK to a pair of PGBLK and TASK then the following should help:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<xsl:output indent="yes"/>

<xsl:template match="RTM">
    <REFERENCES DATA="{current-date()}">
        <xsl:apply-templates/>
    </REFERENCES>
</xsl:template>

<xsl:template match="PGBLK">
    <REF>
        <xsl:apply-templates select="TASK"/>
    </REF>
</xsl:template>

<xsl:template match="TASK">
    <PGBLK>
        <xsl:value-of select="../((@CHAPNBR, @SECTNBR, @SUBJNBR, @PGBLKNBR)/string(), '0')" separator="-"/>
    </PGBLK>
    <xsl:copy>
        <xsl:value-of select="@CHAPNBR, @SECTNBR, @SUBJNBR, @FUNC, @SEQ" separator="-"/>
    </xsl:copy>
</xsl:template>

</xsl:transform>

http://xsltransform.net/ehVYZP2


问:
IOS 11.1 SecurityError (DOM Exception 18): Blocked attempt to use history.replaceState() to change session history URL
I am developing a mobile app using Cordova and jQuery Mobile.  My app was working fine for iOS 11.0.3 and then when iOS 11.1 came out, I am getting an error and unable to click on any links.  The error I get in the safari error console is "SecurityError (DOM Exception 18): Blocked attempt to use history.replaceState() to change session history URL."  I have added <meta http-equiv="Content-Security-Policy" content="default-src * data: blob: ws: wss: gap://ready file://*; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'; connect-src * ws: wss:;"> because I thought it might be part of the Content Security Policy but I am still receiving the same error.  I am using jQuery Mobile 1.4.5 and jQuery 2.1.1.

答:
i have exactly the same issue.

Disabling html5 mode worked for me (as im not using route or state providers)


问:
is there an easier way to set a view's origin and size on iphone
Shorter than

```<code>CGRect rect = self.webView.frame;
rect.origin = CGPointMake(0, 120);
self.webView.frame = rect;
</code>```

Or is this the shortest way (or efficient)

答:
There are several ways to position a view.  As donkim suggested, you could use CGRectMake.  Other options include setting the transform, or setting the center, if those are easier to deal with.  Usually, CGRectMake is the way to go, but I'd like to put these methods here just in case they are more useful in your case:

```<code>//Sets the webView's center, automatically adjusting the frame
self.webView.center = CGPointMake(x,y);
</code>```

or

```<code>//Moves where the webview shows up away from its current location, but does not technically adjust its location.
self.webView.transform = CGAffineTransformMakeTranslation(0,120);
</code>```

Body:
Shorter than

CGRect rect = self.webView.frame;
rect.origin = CGPointMake(0, 120);
self.webView.frame = rect;

Or is this the shortest way (or efficient)

Body:
There are several ways to position a view.  As donkim suggested, you could use CGRectMake.  Other options include setting the transform, or setting the center, if those are easier to deal with.  Usually, CGRectMake is the way to go, but I'd like to put these methods here just in case they are more useful in your case:

//Sets the webView's center, automatically adjusting the frame
self.webView.center = CGPointMake(x,y);

or

//Moves where the webview shows up away from its current location, but does not technically adjust its location.
self.webView.transform = CGAffineTransformMakeTranslation(0,120);


问:
R help - function on multiple data frame columns
I would like to use a function to repeat a set of procedures on four columns in a data frame. Ultimately I need a long data frame containing all the output. Here is my data frame:

```<code>> sample_data
# A tibble: 10 x 7
      REVENUEID AMOUNT  YEAR REPORT_CODE PAYMENT_METHOD INBOUND_CHANNEL  AMOUNT_CAT
          <chr>  <dbl> <chr>       <chr>          <chr>           <chr>      <fctr>
 1 rev-24985629     30  FY18           S          Check            Mail     [25,50)
 2 rev-22812413      1  FY16           Q          Other      Canvassing   [0.01,10)
 3 rev-23508794    100  FY17           Q    Credit card             Web   [100,250)
 4 rev-23506121    300  FY17           S    Credit card            Mail   [250,500)
 5 rev-23550444    100  FY17           S    Credit card             Web   [100,250)
 6 rev-21508672     25  FY14           J          Check            Mail     [25,50)
 7 rev-24981769    500  FY18           S    Credit card             Web [500,1e+03)
 8 rev-23503684     50  FY17           R          Check            Mail     [50,75)
 9 rev-24982087     25  FY18           R          Check            Mail     [25,50)
10 rev-24979834     50  FY18           R    Credit card             Web     [50,75)
</code>```

Here is my code:

```<code>AMOUNT_CAT<- sample_data %>% group_by(AMOUNT_CAT,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=AMOUNT_CAT) %>% mutate(REPORT_CATEGORY="AMOUNT_CAT")
INBOUND_CHANNEL<- sample_data %>% group_by(INBOUND_CHANNEL,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=INBOUND_CHANNEL) %>% mutate(REPORT_CATEGORY="INBOUND_CHANNEL")
PAYMENT_METHOD<- sample_data %>% group_by(PAYMENT_METHOD,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=PAYMENT_METHOD) %>% mutate(REPORT_CATEGORY="PAYMENT_METHOD")
REPORT_CODE<- sample_data %>% group_by(REPORT_CODE,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=REPORT_CODE) %>% mutate(REPORT_CATEGORY="REPORT_CODE")
final_product<-bind_rows(REPORT_CODE,PAYMENT_METHOD,INBOUND_CHANNEL,AMOUNT_CAT)
</code>```

Here is the final product of that code:

```<code>       > final_product
        # A tibble: 27 x 5
        # Groups:   REPORT_VALUE [16]
           REPORT_CATEGORY REPORT_VALUE  YEAR   num total

                 <chr>        <chr> <chr> <int> <dbl>
     1     REPORT_CODE            J  FY14     1    25
     2     REPORT_CODE            Q  FY16     1     1
     3     REPORT_CODE            Q  FY17     1   100
     4     REPORT_CODE            R  FY17     1    50
     5     REPORT_CODE            R  FY18     2    75
     6     REPORT_CODE            S  FY17     2   400
     7     REPORT_CODE            S  FY18     2   530
     8  PAYMENT_METHOD        Check  FY14     1    25
     9  PAYMENT_METHOD        Check  FY17     1    50
    10  PAYMENT_METHOD        Check  FY18     2    55
    # ... with 17 more rows
</code>```

Here is my attempt to condense the code to make it smarter and more efficient (it doesn't work):

```<code>cat.list <- c("REPORT_CODE","PAYMENT_METHOD","INBOUND_CHANNEL","AMOUNT_CAT")
repeat_procs <- lapply(cat.list, function(x) x <- sample_data %>% group_by(x,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=x) %>% mutate(REPORT_CATEGORY="x")
</code>```

Can someone please advise me on how to write "smarter" code that doesn't repeat as often?

Thanks!

答:
You need to parse the strings to symbols (rlang::sym) and unquote them in group_by and rename like the following. Another thing to note is that your cat.list is already a string vector, so there is no need to add double quotes around x in mutate:

```<code>library(dplyr)
library(rlang)

cat.list <- c("REPORT_CODE","PAYMENT_METHOD","INBOUND_CHANNEL","AMOUNT_CAT")
repeat_procs <- lapply(cat.list, function(x){
  final_data <- sample_data %>%
    group_by(!!sym(x), YEAR) %>%
    summarize(num=n(),total=sum(AMOUNT)) %>%
    rename(REPORT_VALUE=!!sym(x)) %>%
    mutate(REPORT_CATEGORY=x)
}) %>%
  bind_rows()
</code>```

Result:

```<code>> repeat_procs
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE   YEAR   num total REPORT_CATEGORY
          <chr> <fctr> <int> <int>           <chr>
 1            J   FY14     1    25     REPORT_CODE
 2            Q   FY16     1     1     REPORT_CODE
 3            Q   FY17     1   100     REPORT_CODE
 4            R   FY17     1    50     REPORT_CODE
 5            R   FY18     2    75     REPORT_CODE
 6            S   FY17     2   400     REPORT_CODE
 7            S   FY18     2   530     REPORT_CODE
 8        Check   FY14     1    25  PAYMENT_METHOD
 9        Check   FY17     1    50  PAYMENT_METHOD
10        Check   FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows
</code>```

Body:
I would like to use a function to repeat a set of procedures on four columns in a data frame. Ultimately I need a long data frame containing all the output. Here is my data frame:

> sample_data
# A tibble: 10 x 7
      REVENUEID AMOUNT  YEAR REPORT_CODE PAYMENT_METHOD INBOUND_CHANNEL  AMOUNT_CAT
          <chr>  <dbl> <chr>       <chr>          <chr>           <chr>      <fctr>
 1 rev-24985629     30  FY18           S          Check            Mail     [25,50)
 2 rev-22812413      1  FY16           Q          Other      Canvassing   [0.01,10)
 3 rev-23508794    100  FY17           Q    Credit card             Web   [100,250)
 4 rev-23506121    300  FY17           S    Credit card            Mail   [250,500)
 5 rev-23550444    100  FY17           S    Credit card             Web   [100,250)
 6 rev-21508672     25  FY14           J          Check            Mail     [25,50)
 7 rev-24981769    500  FY18           S    Credit card             Web [500,1e+03)
 8 rev-23503684     50  FY17           R          Check            Mail     [50,75)
 9 rev-24982087     25  FY18           R          Check            Mail     [25,50)
10 rev-24979834     50  FY18           R    Credit card             Web     [50,75)

Here is my code:

AMOUNT_CAT<- sample_data %>% group_by(AMOUNT_CAT,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=AMOUNT_CAT) %>% mutate(REPORT_CATEGORY="AMOUNT_CAT")
INBOUND_CHANNEL<- sample_data %>% group_by(INBOUND_CHANNEL,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=INBOUND_CHANNEL) %>% mutate(REPORT_CATEGORY="INBOUND_CHANNEL")
PAYMENT_METHOD<- sample_data %>% group_by(PAYMENT_METHOD,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=PAYMENT_METHOD) %>% mutate(REPORT_CATEGORY="PAYMENT_METHOD")
REPORT_CODE<- sample_data %>% group_by(REPORT_CODE,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=REPORT_CODE) %>% mutate(REPORT_CATEGORY="REPORT_CODE")
final_product<-bind_rows(REPORT_CODE,PAYMENT_METHOD,INBOUND_CHANNEL,AMOUNT_CAT)

Here is the final product of that code:

       > final_product
        # A tibble: 27 x 5
        # Groups:   REPORT_VALUE [16]
           REPORT_CATEGORY REPORT_VALUE  YEAR   num total

                 <chr>        <chr> <chr> <int> <dbl>
     1     REPORT_CODE            J  FY14     1    25
     2     REPORT_CODE            Q  FY16     1     1
     3     REPORT_CODE            Q  FY17     1   100
     4     REPORT_CODE            R  FY17     1    50
     5     REPORT_CODE            R  FY18     2    75
     6     REPORT_CODE            S  FY17     2   400
     7     REPORT_CODE            S  FY18     2   530
     8  PAYMENT_METHOD        Check  FY14     1    25
     9  PAYMENT_METHOD        Check  FY17     1    50
    10  PAYMENT_METHOD        Check  FY18     2    55
    # ... with 17 more rows

Here is my attempt to condense the code to make it smarter and more efficient (it doesn't work):

cat.list <- c("REPORT_CODE","PAYMENT_METHOD","INBOUND_CHANNEL","AMOUNT_CAT")
repeat_procs <- lapply(cat.list, function(x) x <- sample_data %>% group_by(x,YEAR) %>% summarize(num=n(),total=sum(AMOUNT)) %>% rename(REPORT_VALUE=x) %>% mutate(REPORT_CATEGORY="x")

Can someone please advise me on how to write "smarter" code that doesn't repeat as often?

Thanks!

Body:
You need to parse the strings to symbols (rlang::sym) and unquote them in group_by and rename like the following. Another thing to note is that your cat.list is already a string vector, so there is no need to add double quotes around x in mutate:

library(dplyr)
library(rlang)

cat.list <- c("REPORT_CODE","PAYMENT_METHOD","INBOUND_CHANNEL","AMOUNT_CAT")
repeat_procs <- lapply(cat.list, function(x){
  final_data <- sample_data %>%
    group_by(!!sym(x), YEAR) %>%
    summarize(num=n(),total=sum(AMOUNT)) %>%
    rename(REPORT_VALUE=!!sym(x)) %>%
    mutate(REPORT_CATEGORY=x)
}) %>%
  bind_rows()

Result:

> repeat_procs
# A tibble: 27 x 5
# Groups:   REPORT_VALUE [16]
   REPORT_VALUE   YEAR   num total REPORT_CATEGORY
          <chr> <fctr> <int> <int>           <chr>
 1            J   FY14     1    25     REPORT_CODE
 2            Q   FY16     1     1     REPORT_CODE
 3            Q   FY17     1   100     REPORT_CODE
 4            R   FY17     1    50     REPORT_CODE
 5            R   FY18     2    75     REPORT_CODE
 6            S   FY17     2   400     REPORT_CODE
 7            S   FY18     2   530     REPORT_CODE
 8        Check   FY14     1    25  PAYMENT_METHOD
 9        Check   FY17     1    50  PAYMENT_METHOD
10        Check   FY18     2    55  PAYMENT_METHOD
# ... with 17 more rows


问:
geom_text() & color gradient
I am looking to set a color gradient from green for low and red for high on the geom_text function. My code is as follows:

```<code>mydata <-  data.frame(R_Test_Data)

datatime <- mydata$TIMESTAMP
wind_speed <- mydata$WS_ms_Avg
wind_direction <-mydata$WS_ms_WVc

ggplot(data = mydata, aes(x = datatime, y = wind_speed))+
  geom_line() +
  geom_text(aes(angle=-wind_direction + 270), label="→",
            colour = wind_speed, size = 7 ) +
 scale_colour_gradient(low="green", high="red")
</code>```

I am looking for something kind of like this:

答:
Map colour to to a numeric variable - e.g. this maps color to y by specifying color=y within aes:

```<code>set.seed(1);df <- data.frame(x = 1:10, y = 1:10, angle = runif(10,90,180))
library(ggplot2)
ggplot(df, aes(x,y)) +
  geom_text(aes(angle=angle, color=y), label="-", size = 12) +
  scale_colour_distiller(palette="RdYlGn")
</code>```

Title: geom_text() & color gradient

Body:
I am looking to set a color gradient from green for low and red for high on the geom_text function. My code is as follows:

mydata <-  data.frame(R_Test_Data)

datatime <- mydata$TIMESTAMP
wind_speed <- mydata$WS_ms_Avg
wind_direction <-mydata$WS_ms_WVc

ggplot(data = mydata, aes(x = datatime, y = wind_speed))+
  geom_line() +
  geom_text(aes(angle=-wind_direction + 270), label="→",
            colour = wind_speed, size = 7 ) +
 scale_colour_gradient(low="green", high="red")

I am looking for something kind of like this:

Body:
Map colour to to a numeric variable - e.g. this maps color to y by specifying color=y within aes:

set.seed(1);df <- data.frame(x = 1:10, y = 1:10, angle = runif(10,90,180))
library(ggplot2)
ggplot(df, aes(x,y)) +
  geom_text(aes(angle=angle, color=y), label="-", size = 12) +
  scale_colour_distiller(palette="RdYlGn")


问:
Confused about Ruby on Rails routes.rb syntax
Suppose I had the following code in my routes.rb file.

```<code>  get '/dashboard', to: 'dashboard#index', :as => 'dashboard'
</code>```

I know what's going on (a public url being mapped to a specific controller/view file which will process and return the request). That is not what I am confused about.

As a Ruby beginner, I'm confused about what Ruby code convention this is. It doesn't look like the correct way to declare a variable or call a method? What exactly is going on and is this some sort of shorthand form to call a method?

```<code>get("/dashboard", "dashboard#index", "dashboard")
</code>```

答:
This is a common way to allow options to be passed to a method. Like the following:

```<code>def do_something(subject, options = {})
  subject.perform_something
  subject.perform_caching if options[:cache]
  subject.send_report unless options[:skip_reporting]
  # etc.
end
</code>```

So you can call:

```<code>something(some_object)
something(some_object, cache: true)
something(some_object, skip_reporting: true, cache: true)
</code>```

You can even set up defaults, like this:

```<code>def do_something_else(subject, options = {})
  options = { cache: true, skip_reporting: false }.merge(options)
  subject.perform_something
  subject.perform_caching if options[:cache]
  subject.send_report unless options[:skip_reporting]
end
</code>```

So that by default if no cache options if given, it will be true.

Body:
Suppose I had the following code in my routes.rb file.

  get '/dashboard', to: 'dashboard#index', :as => 'dashboard'

I know what's going on (a public url being mapped to a specific controller/view file which will process and return the request). That is not what I am confused about.

As a Ruby beginner, I'm confused about what Ruby code convention this is. It doesn't look like the correct way to declare a variable or call a method? What exactly is going on and is this some sort of shorthand form to call a method?

get("/dashboard", "dashboard#index", "dashboard")

Body:
This is a common way to allow options to be passed to a method. Like the following:

def do_something(subject, options = {})
  subject.perform_something
  subject.perform_caching if options[:cache]
  subject.send_report unless options[:skip_reporting]
  # etc.
end

So you can call:

something(some_object)
something(some_object, cache: true)
something(some_object, skip_reporting: true, cache: true)

You can even set up defaults, like this:

def do_something_else(subject, options = {})
  options = { cache: true, skip_reporting: false }.merge(options)
  subject.perform_something
  subject.perform_caching if options[:cache]
  subject.send_report unless options[:skip_reporting]
end

So that by default if no cache options if given, it will be true.


问:
Specifying the DB to connect with gcloud sql
When connecting to a Google Cloud SQL instance, is there a way to specify the database I want to connect to?

This is the command I execute and the error I get:

```<code>$ gcloud beta sql connect MY_INSTANCE --user=MY_USER
Whitelisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [MY_USER].Password for user MY_USER:
psql: FATAL:  database "MY_USER" does not exist
</code>```

It seems to try to connect to a database that has the same name than the user, but what when that's not the case? (I don't want to create a dummy DB called MY_USER just to be able to jump to the DB I want).

Here are the docs for the command gcloud beta sql, but I don't see anything useful for this there: https://cloud.google.com/sdk/gcloud/reference/beta/sql/connect

答:
gcloud sql connect does not currently allow you to specify the database name. There is a open issue to add it: https://issuetracker.google.com/issues/69314375

In the meantime, you can work around this by utilizing the PGDATABASE environment variable:

e.g.

```<code>PGDATABASE=mydb gcloud sql connect myinstance
</code>```

You could create a shell alias to do this for you.

Body:
When connecting to a Google Cloud SQL instance, is there a way to specify the database I want to connect to?

This is the command I execute and the error I get:

$ gcloud beta sql connect MY_INSTANCE --user=MY_USER
Whitelisting your IP for incoming connection for 5 minutes...done.
Connecting to database with SQL user [MY_USER].Password for user MY_USER:
psql: FATAL:  database "MY_USER" does not exist

It seems to try to connect to a database that has the same name than the user, but what when that's not the case? (I don't want to create a dummy DB called MY_USER just to be able to jump to the DB I want).

Here are the docs for the command gcloud beta sql, but I don't see anything useful for this there: https://cloud.google.com/sdk/gcloud/reference/beta/sql/connect

Body:
gcloud sql connect does not currently allow you to specify the database name. There is a open issue to add it: https://issuetracker.google.com/issues/69314375

In the meantime, you can work around this by utilizing the PGDATABASE environment variable:

e.g.

PGDATABASE=mydb gcloud sql connect myinstance

You could create a shell alias to do this for you.


问:
loop through string to find substring
I have this string:

```<code>text = "book//title//page/section/para";
</code>```

I want to go through it to find all // and / and their index.

I tried doing this with:

```<code>if (text.Contains("//"))
{
    Console.WriteLine(" // index:  {0}  ", text.IndexOf("//"));
}
if (text.Contains("/"))
{
    Console.WriteLine("/ index:  {0}  :", text.IndexOf("/"));
}
</code>```

I was also thinking about using:

```<code>Foreach(char c in text)
</code>```

but it will not work since // is not a single char.

How can I achieve what I want?

I tried this one also but did not display result

```<code>string input = "book//title//page/section/para";
string pattern = @"\/\//";

Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = rgx.Matches(input);
 if (matches.Count > 0)
  {
      Console.WriteLine("{0} ({1} matches):", input, matches.Count);
      foreach (Match match in matches)
         Console.WriteLine("   " + input.IndexOf(match.Value));
 }
</code>```

Thank you in advance.

答:
Simple:

```<code>var text = "book//title//page/section/para";
foreach (Match m in Regex.Matches(text, "//?"))
    Console.WriteLine(string.Format("Found {0} at index {1}.", m.Value, m.Index));
</code>```

Output:

```<code>Found // at index 4.
Found // at index 11.
Found / at index 17.
Found / at index 25.
</code>```

Title: loop through string to find substring

Body:
I have this string:

text = "book//title//page/section/para";

I want to go through it to find all // and / and their index.

I tried doing this with:

if (text.Contains("//"))
{
    Console.WriteLine(" // index:  {0}  ", text.IndexOf("//"));
}
if (text.Contains("/"))
{
    Console.WriteLine("/ index:  {0}  :", text.IndexOf("/"));
}

I was also thinking about using:

Foreach(char c in text)

but it will not work since // is not a single char.

How can I achieve what I want?

I tried this one also but did not display result

string input = "book//title//page/section/para";
string pattern = @"\/\//";

Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
MatchCollection matches = rgx.Matches(input);
 if (matches.Count > 0)
  {
      Console.WriteLine("{0} ({1} matches):", input, matches.Count);
      foreach (Match match in matches)
         Console.WriteLine("   " + input.IndexOf(match.Value));
 }

Thank you in advance.

Body:
Simple:

var text = "book//title//page/section/para";
foreach (Match m in Regex.Matches(text, "//?"))
    Console.WriteLine(string.Format("Found {0} at index {1}.", m.Value, m.Index));

Output:

Found // at index 4.
Found // at index 11.
Found / at index 17.
Found / at index 25.